对于一对同样大小的二维数组和一维数组,
他们在汇编中都是在栈里尺寸相等的一段连续空间,除了入口地址之外,没有区别。
真正让他们产生区别的是代码中后续对各个数组进行的操作:
操作二维数组时,编译器自动将其指向的数据类型计算出来,然后翻译成对应的汇编代码进行操作。
比如对于int arr[4][10]来说:
arr[2]之所以能取到对应的arr[2][0]的地址,
是由于C的编译器让arr指向的数据类型为 int * 10 = 40字节,
arr[2]就等于(arr的地址 + 2*40)之后的地址。
C编译器直接把这个表达式翻译成汇编,汇编并不知道arr能偏移多少。
- 栈空间层面
同样大小的一维、二维数组,在汇编里就是两段等大、连续的栈内存,只有基地址不同,无任何区别。 - 类型与偏移层面
数组的类型信息(步长)只存在于编译期,汇编不存储任何类型、维度信息。 - 操作时的区别
当你操作数组时,编译器根据类型算出偏移量,直接把计算规则写进汇编指令:int arr[4][10]→ 类型int (*)[10]→ 步长 40 字节arr[2]→ 编译器翻译为:arr 基地址 + 2*40- 最终得到
&arr[2][0]
- 核心真相汇编只负责执行地址计算,不知道偏移规则;规则是编译器在编译时根据类型定好的。
数组维度是给编译器看的,不是给汇编 / CPU 看的;编译器根据类型算偏移,汇编只认最终地址。