C/C++二维数组名和二级指针


1. 指针

1.1 一个指针包含两方面:a) 地址值;b) 所指向的数据类型。

1.2 解引用操作符(dereference operator)会根据指针当前的地址值,以及所指向的数据类型,访问一块连续的内存空间(大小由指针所指向的数据类型决定),将这块空间的内容转换成相应的数据类型,并返回左值。

有时候,两个指针的值相同,但数据类型不同,解引用取到的值也是不同的,例如,

	char str[] ={0, 1, 2, 3};       /* 以字符的ASCII码初始化 */

	char * pc = &str[0];		/* pc指向str[0],即0 */

	int * pi = (int *) pc;		/* 指针的“值”是个地址,32位。 */
此时,pc和pi同时指向str[0],但*pc的值为0(即,ASCII码值为0的字符);而*pi的值为50462976。或许把它写成十六进制会更容易理解:0x03020100(4个字节分别为3,2,1,0)。我想你已经明白了,指针pi指向的类型为int,因此在解引用时,需要访问4个字节的连续空间,并将其转换为int返回。


2. 数组

2.1 数组名和指针

通常我们认为数组名是一个指针常量(例如,int a[10]; 那么a是一个int * const),这种理解是不全面的,正确的理解如下:

作为右值(例如,赋值语句右边)时数组名可视为指针常量(系统自动转换);作为左值,例如取地址,sizeof,则不能视为指针。

sizeof(一个数组)返回的是数组大小*每个元素占字节数;而sizeof(一个指针)返回4。


2.2 二维数组

实际上,不管是一维还是多维数组,都是内存中一块线性连续空间,因此在内存级别上,其实都只是一维。



(图片在参考资料2基础上稍作更改)


做如下定义:

	int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
	
	int ** p;

	p = (int**)a;		/* 不做强制类型转换会报错 */

说明:

1)p是一个二级指针,它首先是一个指针,指向一个int*;

2)a是二维数组名,它首先是一个指针,指向一个含有4个元素的int数组;

由此可见,a和p的类型并不相同,如果想将a赋值给p,需要强制类型转换。

3. 为什么不能将二维数组名传递给二级指针?

假如我们将a赋值给p,p = (int**)a; 既然p是二级指针,那么当然可以这么用:**p; 这样会出什么问题呢?

1)首先看一下p的值,p指向a[0][0],即p的值为a[0][0]的地址;

2)再看一下*p的值,p所指向的类型是int*,占4字节,根据前面所讲的解引用操作符的过程:从p指向的地址开始,取连续4个字节的内容。得到的正式a[0][0]的值,即0。

3)再看一下**p的值,诶,报错了?当然报错了,因为你访问了地址为0的空间,而这个空间你是没有权限访问的。


实际上这是某一年华为的面试题。感兴趣的还可以把a的类型定义为char类型的二维数组,看看会发生什么。


4. 二维数组和二级指针相关的参数匹配


(来源参考资料3)

5. 那么问题来了,下题答案是?



参考资料:

1. http://blog.sina.com.cn/s/blog_5c6f793801019t3t.html

2. http://c.biancheng.net/cpp/html/477.html

3. http://www.360doc.com/content/12/0421/23/8302596_205542017.

-----------------------------------------------------------------------------


以上,不知道我有没有说清楚,有问题欢迎评论留言。



C语言中的二级指针指向二维数组意味着二级指针指向一个指针数组,而指针数组的每个元素又指向一个一维数组。以二级指针来访问二维数组能够更灵活地进行矩阵的操作。 首先,我们需要先定义一个指针数组,每个指针元素都指向一个一维数组。假设我们要定义一个3行4列的二维数组: ```c int** array; // 定义二级指针 array = (int**) malloc(3 * sizeof(int*)); // 为指针数组分配内存空间 ``` 接下来,我们通过循环为每个指针元素分配一维数组的内存空间,并将其地址赋给二级指针的元素: ```c int i, j; for (i = 0; i < 3; i++) { array[i] = (int*) malloc(4 * sizeof(int)); // 为每个一维数组分配内存空间 for (j = 0; j < 4; j++) { array[i][j] = i * 4 + j; // 初始化数组元素的值 } } ``` 这样,我们就成功地用二级指针指向了一个3行4列的二维数组。 使用二级指针访问二维数组时,我们可以通过对二级指针的解引用来获取指针数组的元素的地址,然后再通过解引用该地址来获取一维数组的元素值。假设我们要访问第2行第3列的元素: ```c int value = *(*(array + 1) + 2); // 访问第2行第3列的元素值 ``` 其中,`(array + 1)`表示指针数组的第2个指针元素,`+ 2`表示偏移2个`int`类型的内存空间,`*`操作符分别对指向一维数组的指针和偏移后的地址进行解引用操作。 最后,记得在使用完二维数组后释放内存空间,避免内存泄漏: ```c for (i = 0; i < 3; i++) { free(array[i]); // 释放每个一维数组的内存空间 } free(array); // 释放指针数组的内存空间 ``` 以上就是使用二级指针指向二维数组的基本操作。通过二级指针,我们可以更自由地操作二维数组,实现更复杂的算法和功能。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值