程序的机器级表示 - 数组的分配和访问
基本原则
数组:将一组标量数据聚集成更大数据类型的方式。 在C语言中,可以产生指向数组中元素的指针,并对指针进行运算。 对于数据类型T和整数常数N,声明语句如下:
如果起始位置标示为x,则这段代码有两个作用
在内存中分配一个L*N字节的连续区域,其中L是数据类型T的大小(单位为字节)
标识符A,可以用A来作为指向数组开头的指针,这个指针的值就是x
可以用0~N-1的整数索引来访问该数组的元素,数组i被保存在x+L*i的位置。 对于以下数组声明:
数组元素与位置的关系如下
之前有关于如何访问内存中的数据,可以发现内存访问指令可以来简化数组访问 假设E是一个int数组,而我们想计算E[i],如果E的起始地址在%rdx,i存放在%rcx,则 (%rdx,%rcx,4)会执行 %rdx+4*%rcx
指针运算
C语言允许对指针进行运算,而计算出来的值会根据该指针引用的数据类型的大小进行伸缩。
也就是说,如果 P 是一个执行类型 T 的数据的指针,P 的值为 Xp,那么表达式P+i 的值为 Xp+L*i,这里 L 是数据类型T的大小。
假设整型数组 E 的起始地址和整数索引 i 分别存放在寄存器 %edx 和 %ecx 中,下面是每个表达式的汇编代码实现,结果存放在 %eax 中。
ps: leaq 指令用来计算地址
定长数组
要理解定长和变长数组,我们必须搞清楚一个概念,就是说这个“定”和“变”是针对什么来说的。在这里我们说,这两个字是针对编译器来说的,也就是说,如果在编译时数组的长度确定,我们就称为定长数组,反之则称为变长数组。
反编译之后的代码
去掉了索引j,把所有数组引用都转换为指针引用, 指针Aptr指向A的i行, 指针Bptr指向B的k列,Bptr+N就可以指向下一列 指针Bend指向B的k列的最后一个元素,用于终止条件判断。
变长数组
与定长数组不同,变长数组中元素的个数可以是一个表达式,表达式可以在数组分配时才计算。
与定长数组计算i的地址不同,动态的版本必须用乘法指令对i伸缩n倍。
参考资料
版权声明: 本文为 InfoQ 作者【引花眠】的原创文章。
原文链接:【http://xie.infoq.cn/article/4282080e354a555d5d9e5a368】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论