第三天2017/03/30(下午:二级指针的(输出)内存模型)

本文深入探讨了数组和数组指针的概念,包括数组地址与首元素地址的区别、数组指针的定义与使用方法,以及一维和多维数组在内存中的表现形式。并通过示例代码演示了如何使用不同类型指针来操作数组。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【备用知识——字符串的操作】
模块讲解:数组、数组指针

void *memset(void *s, int ch, size_t n);
函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。
memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法

1) 数组首元素的地址和数组地址是两个不同的概念(类型决定步长!)
例:int a[10];
    a:代表数组首元素的地址 (a代表数组元素类型,即a[0])
    &a:数组的地址(&a代表数组类型,即int [10])

(2)以一维数组为例
#include <iostream>
using namespace std;
int main()
{   //①定义数组
    typedef int(MTYPE)[5];//讲解此句话的含义
    MTYPE array; //等价于int array[5];
    for(int i = 0; i<5; i++)
    {
        array[i] = i;
        cout<<array[i]<<endl;
    }

//定义一个指向数组类型的指针的三种方式
    //②:用定义的数组类型MTYPE定义数组指针变量(方式一)
    MTYPE *pArr = &array; //pArr指向数组类型(即指向&array,而不是指向数组元素)
    for(int i = 0; i<5; i++)
    {
        cout<<(*pArr )[i]<<endl;
    }
    //②:定义一个数组指针类型pMTYPE,用pMTYPE定义数组指针变量(方式二)
    typedef int(*pMTYPE)[5]; //类比typedef int(MTYPE)[5];//讲解此句话的含义
    pMTYPE ptr = &array; //此处的 *ptr = 数组的地址,即&array。
    //②:直接定义一个数组指针ptrArr(方式三)
    char (*ptrArr)[5]; //ptrArr是一个指向char[5]数组的指针,它指向数组,而不是指向数组的元素,因此给它赋值时用数组的地址,而不是数组元素的地址。
    ptrArr = &array;  //注意:此处不是array(&array[0]数组首元素的地址),而是&array(数组的地址)

    //数组指针ptrArr的使用:
        首先把一个数组地址赋值给数组指针ptrArr
        然后用(*ptrArr)去取出该数组的地址
        最后进行使用,使用方式(*ptrArr)[i]
}
【解读】    typedef int(MTYPE)[5];的含义

(3)※【重点来了】数组名加一增加的步长是多少?(【注】多维数组和一维数组不同)
#include <iostream>
using namespace std;
int main()
{//一维数组
    int c1[5] ; 
    cout<<(int)c1    <<endl;
    cout<<(int)(c1+1)<<endl;  //一维数组的数组名+1,地址增加一个元素sizeof(c1[i])的大小

 //二维数组
    int c2[3][5];
    cout<<(int)c2    <<endl;
    cout<<(int)(c2+1)<<endl;  //二维数组的数组名+1,地址增加 5*sizeof(c2[i][j]) 的大小

【总结】
//  一维数组的数组名代表首元素的地址,相当于&c1[0];因此c1+1的地址增量是sizeof(int)

//  二维数组的数组名表示对应的数组指针,相当于int (*c2)[5];因此c2+1的地址增量是sizeof(int [5])
//  三维数组的数组名表示对应的数组指针,相当于int (*c2)[5][4];因此c3+1的地址增量是sizeof(int [5][4])
//  以此类推到N维数组

【综上所述】一维数组名自成一派,多维数组名实质上表示的是数组指针。
    getchar();
}
常见返回值问题
char* getchar()
{
    //char *p1 = "AAAA";  //常量区
    //return p1; //返回成功
    char p2[100] = "AAAA";  //局部变量区
    return p2; //返回失败
}

==============================================
二级指针的(输出)内存模型

//在被调函数中分配内存,把结果给甩出来(甩给主调函数)
//这种模型:实参是地址或者引用
#include <iostream>
using namespace std;
//二级指针的输出模型
struct student
{
    char name[100];
    int age;
};
struct student* create1()
{
    struct student* s = (struct student*)malloc(sizeof(struct student)); //在被调函数中分配内存
    return s;
}

int create2(struct student** s)
{
    if(s==NULL) //如果传进去的实参是无效的值(即传进去的实参的地址是NULL), 而不能用 if(*s==NULL)
        return 0;
    *s = (struct student*)malloc(sizeof(struct student));
    return 1;
}
int main()
{
//形式一
    struct student *stu1 = NULL;
    stu1 = create1();

//形式二
    struct student *stu2 = NULL;
    create2(&stu2);

    return 0;
}

二级指针的易犯错误模型以及相关知识

(1)char buf[100];//buf是const常量,不能被修改
(2)编译器会把p[i]转换成*(p+i)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值