C语言深度解剖——读书笔记-10、指针和数组

本文深入探讨了C语言中的二维数组和多级指针,解析了二维数组的存储方式以及如何通过指针操作数组。通过示例说明了指针变量作为函数参数时的传递方式,解释了在`GetMemory`函数中直接传递指针为何无法改变实参值,并提供了两种解决方案:返回指针或使用二级指针。

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

4.5    多维数组和多级指针


4.5.1    二维数组(重点)

1、二维数组的布局:只需记住二维数组的存储也是线性的,编译器总是把二维数组看成一个一维数组,而一维数组的每一个元素又是一个数组。

逗号表达式的知识:用逗号运算符连接的式子叫做逗号表达式,它的值是最右边的表达式的值。

2、&p[4][2] - &a[4][2]的值为多少?

问题:

int a[5][5];
int (*p)[4];
p = a;

问:&p[4][2] - &a[4][2]的值为多少

分析: 值为 - 4。

 当数组名a为右值时,代表的是数组首元素的首地址。这里的a为二维数组,我们把数组a看作是包含5个int类型元素的一维数组,里面再存储了一个一维数组。如此,则a在这里表示的是a[0]的首地址,它的值是一个指向它第一个元素的指针,所以a是一个指向包含5个整型元素的数组的指针;a+1是一维数组的第二个元素即a[1];a[4]表示的是一维数组a的第五个元素(每个元素里又存储了一个一维数组)。

所以,&a[4][2] 表示的是&a[0][0] + 4*5*sizeof(int) + 2 * sizeof(int)。

p 是指向一个包含4个元素的数组的指针,也就是说p+1 表示的是指针p向后移动了一个“包含4个int类型元素的数组”。这里1 的单位是p指向的空间,即4*sizeof(int)。所以,p[4]相对于p[0]来说是向后移动了4个“包含4个int类型元素的数组”,即&p[4]表示的是&p[0] + 4*4*sizeof(int)。由于p被初始化为&a[0],所以&p[4][2]表示是&a[0][0] + 4*4*sizeof(int) + 2 * sizeof(int)。



4.6    数组参数和指针参数

1、能否把指针变量本身传给一个函数

例:

void   fun(char  *p)

{

     char  c= p[3];  

}

int   main()

{

      char  *p2= "abcdefg";

      fun(p2);

       retrun  0;

}

这个函数调用真的把p2本身传递到了fun函数内部吗?

解析:p2是main函数内的一个局部变量,它只在main函数内部有效。既然它是内部函数,fun函数肯定无法使用p2的真身。那函数调用怎么办?好办:对实参做一份备份并传递给被调用函数,即对p2做一份备份,假设其设备名为_p2,那么传递到函数内部的就是_p2而非p2本身。


2、无法把指针变量本身传递给一个函数

fun函数实际运行时,用到的都是_p2这个变量而非p2本身。

void GetMemory(char  *p ,int  num)

{

     p = (char *) malloc(num *sizeof(char));

}

int  main()

{

    char  *str =NULL;

    GetMemory(str ,10);

     strcpy(str, "hello");

     free(str);

     return   0;

}

在运行strcpy(str, "hello")语句的时候发生错误。这时候观察str的值,发现仍然为NULL.也就是说str本身并没有改变,我们malloc的内存的地址并没有赋给str,而是赋给了_str。而这个_str是编译器自动分配和回收的,我们根本就无法使用,所以想这样获取一块内存是不行的。


2个解决办法:

(1).用retrun

void GetMemory(char  *p ,int  num)

{

     p = (char *) malloc(num *sizeof(char));

     return   p;

}

int  main()

{

    char  *str =NULL;

    GetMemory(str ,10);

     strcpy(str, "hello");

     free(str);

     return   0;

}

(2)用二级指针

void GetMemory(char  * *p ,int  num)

{

     p = (char *) malloc(num *sizeof(char));

}

int  main()

{

    char  *str =NULL;

    GetMemory(&str ,10);

     strcpy(str, "hello");

     free(str);

     return   0;

}

注意,这里的参数是&str而非str,这样的话传递过去的是str的地址,是一个值。在函数内部,用钥匙(“*”)来开锁:*(&str)其值就是str。所以malloc分配的内存地址是真正赋值给了str本身。


4.6.3    二维数组参数和二级指针参数


数组参数 等效的指针参数
一维数组:float  a[5]指针: float *a
指针数组:  int*  a[5]指针的指针:int  **a
二维数组:char a[4][4]数组的指针:char (*p)[4]




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值