技术问询:C语言中数组是否为指针的语法糖?arr[i]是否是*(arr+i)的语法糖?
嘿,这两个问题是C语言里新手常搞混的经典点,我来给你唠明白~
问题1:C语言中的数组是否属于指针的语法糖?
绝对不是!数组和指针是完全不同的两种实体,别被它们的一些相似用法误导了。
- 数组本质是一块连续分配的内存区域,它本身代表整个内存块,有明确的类型(比如
int arr[5]的类型是int[5])。用sizeof(arr)能直接获取整个数组的字节大小(比如5个int就是20字节,假设int占4字节)。 - 指针则是一个存储内存地址的变量,它的大小只和系统位数有关(32位系统是4字节,64位是8字节),和它指向的对象完全无关。
给你看段代码对比一下:
#include <stdio.h> int main() { int arr[5] = {1,2,3,4,5}; int *p = arr; // 这里数组名arr会隐式转成指向首元素的指针(这是数组退化规则) printf("sizeof(arr) = %zu\n", sizeof(arr)); // 输出20(对应5*4字节) printf("sizeof(p) = %zu\n", sizeof(p)); // 输出4或8,看系统位数 return 0; }
你看,sizeof的结果天差地别,这就直接证明了数组不是指针的语法糖——只是在多数表达式场景下,数组名会自动“退化”成指向首元素的指针而已。
问题2:表达式arr[i]是否是*(arr + i)的语法糖?
这个答案是肯定的,而且这是C语言标准明文规定的!
C语言里,下标运算符[]的定义就是:E1[E2]等价于*(E1 + E2)。有意思的是,因为加法满足交换律,i[arr]这种反着写的形式也是合法的,它等价于*(i + arr),和*(arr + i)完全一样。
用代码来验证:
#include <stdio.h> int main() { int arr[5] = {10,20,30,40,50}; int *p = arr; // 常规数组下标访问 printf("arr[2] = %d\n", arr[2]); // 输出30 // 等价写法 printf("*(arr + 2) = %d\n", *(arr + 2)); // 同样输出30 // 指针也能用下标访问 printf("p[3] = %d\n", p[3]); // 输出40 // 等价写法 printf("*(p + 3) = %d\n", *(p + 3)); // 同样输出40 // 反着写的奇怪用法(合法但不推荐) printf("2[arr] = %d\n", 2[arr]); // 还是输出30,因为2[arr] = *(2 + arr) = *(arr + 2) return 0; }
这里要注意,当arr出现在arr + i里时,它已经触发了数组退化规则,变成了指向首元素的指针,所以arr + i计算的是首地址偏移i个元素的内存地址,解引用后就得到对应位置的元素,这和arr[i]的效果完全一致。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

