C语言对二维数组名解引用为何得到地址而非存储值?
问题原因分析
你的代码没有语法错误,问题出在对C语言数组类型隐式转换规则、指针解引用的类型逻辑认知有误,同时printf格式符的使用不规范:
- C语言中,除了
sizeof、&等少数场景外,数组名在表达式中会自动隐式转换为指向数组首元素的指针。你定义的B是类型为int[2][3]的二维数组,在表达式中会转换为类型为int (*)[3]的指针,指向第一行长度为3的一维数组B[0]。 - 对
int (*)[3]类型的指针做解引用(即*B操作),得到的是类型为int[3]的一维数组(也就是B[0])。这个一维数组作为printf参数传递时,会再次触发数组转指针的规则,被转换为指向它自身首元素B[0][0]的int*类型指针,所以你打印出来的是B[0][0]的地址,不是你预期的数值。
代码修正建议
- 打印地址请使用
%p格式符,且需要将指针强制转换为void*类型,用%d打印指针属于未定义行为,部分系统下会出现输出异常。 - 如果要获取
B[0]指向的第一个int数值,需要对转换后的int*指针再做一次解引用,也就是两次解引用**B,或者用下标写法B[0][0]。
修正后的参考代码:
#include<stdio.h> #include<stdlib.h> int main (void){ int B[2][3] = {{2,3,4},{5,6,7}}; int (*p)[3] = B; // 打印地址用%p,强转void* printf("Address at B[0] is: %p or %p\n", (void*)B, (void*)&B[0]); // 打印B[0][0]的地址 printf ("Address of B[0][0] is: %p\n", (void*)*B); // 打印B[0][0]的数值 printf ("Value at B[0][0] is: %d\n",**B); printf("B + 1 = %p\n", (void*)(B+1)); return 0; }
等价关系梳理
你可以记住以下几个常用的等价关系,方便理解二维数组指针:
B<=>&B[0],类型是int (*)[3],指向整个第一行数组*B<=>B[0]<=>&B[0][0],类型是int*,指向第一行第一个元素**B<=>B[0][0],类型是int,就是第一行第一个元素的数值2
内容的提问来源于stack exchange,提问作者user17364008
相关产品推荐
相关产品推荐

