C语言中不存在数组双重退化?二维数组赋值与访问疑问
二维数组与指针的常见疑问解析
先看示例代码:
int a[2][2] = {{1,2},{3,4}}; int *p; p = *a; // 即使不解引用a也能运行 printf("%d\n", *p); // 输出为1
疑问1:p是int*类型,*a是数组,为何无警告?
- 首先明确
a的类型:a是int[2][2],也就是包含2个元素的数组,每个元素又是int[2]类型的数组。 *a访问的是a的第一个元素,即int[2]类型的数组{1,2}。- 在C语言中,数组在表达式里(除了
sizeof运算、&取地址、字符串字面量初始化数组这几种特殊场景)会自动退化为指向其首元素的指针。所以*a这个int[2]数组,会直接退化成int*类型的指针,指向它的第一个元素(也就是值为1的int变量)。 - 既然
*a退化成了int*,和p的类型完全匹配,编译器自然不会发出警告。
疑问2:打印*p输出1,这在不发生数组双重退化的情况下如何成立?
- 你的误解在于误以为
*a还保持数组类型,但实际上在p = *a这个赋值表达式里,*a已经完成了数组到指针的退化,p拿到的是指向单个int的指针(指向a[0][0]),而非指向子数组的指针。 - 所以
*p就是取这个指针指向的int值,结果自然是1。这里不存在“双重退化”,因为*a本身是数组,只发生了一次退化:从int[2]数组退化为int*指针。
内容的提问来源于stack exchange,提问作者Anthony
相关产品推荐
相关产品推荐

