C语言中array[x][y]表达式是否总是通过指针运算求值?
C语言二维数组下标访问的底层差异
你之前的两个认知完全正确:
- 声明
int array[x][y] = {0};形式的二维数组时,确实会分配一块连续的x*y * sizeof(int)大小的内存,没有额外开销- 通过
int **array两次malloc的方式创建的二维数组,内存分为两部分:x个指针大小的指针数组,加上x块各y个int大小的行数据块,这些行数据块不一定是连续的
核心结论
你提到的array[5][0]语句的处理逻辑,核心取决于array的类型,而非创建方式,编译器不会为普通二维数组生成额外的指针数组,具体差异如下:
1. 普通二维数组int array[x][y]的下标处理
此时array的类型是指向长度为y的int数组的指针(int (*)[y]),下标运算完全是编译期计算偏移:
array[5]等价于*(array + 5),指针步长为y * sizeof(int),直接计算出第5行的首地址,不需要读取任何额外的内存- 再做
[0]等价于*(*(array +5) + 0),直接在第5行首地址的基础上偏移0取元素,整个过程都是直接操作连续的内存块,没有任何指针数组参与。
2. int **类型动态数组的下标处理
此时array的类型是二级int指针(int **),下标运算需要两次内存访问:
array[5]等价于*(array +5),指针步长为sizeof(int*),首先从指针数组的第5个位置读取存储的行地址,这是一次运行时的内存读操作- 再做
[0]就是基于读出来的行地址,偏移0取对应元素,需要第二次内存访问。
3. 关于“是否总是指针运算”的说明
C语言语法规则里a[b]永远等价于*(a + b),所以从语法层面看确实永远是指针运算,但因为运算对象的类型不同,底层生成的CPU指令完全不同,不存在统一的处理逻辑。
内容的提问来源于stack exchange,提问作者Luke Dunn
相关产品推荐
相关产品推荐

