版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
3.8 数组分配和访问
C
语言的数组是一种将标量数据聚集成更大数据类型的方式。
3.8.1 基本原则
对于数据类型 T 和整型常数 N
,声明如下:
T A[N]
;
示例:
数组A
由12
个单字节(char
)元素组成。
数组C
由6
个整数组成,每个需要8
个字节。
B
和D
都是指针指数,因此每个数组元素都是8
个字节。
示例:
int E[i];
假设 E 的地址在 %rdx中
i 存放在 %rcx 中,有
movl (%rdx, %rcx, 4), %eax
即,地址计算了
,并将读取的值存入 %eax
中。
3.8.2 指针运算
C语言允许对指针进行运算,而计算出来的值会根据该指针引用的数据类型的大小进行伸缩。
单操作数操作符&
和*
可以产生指针和间接引用指针。
3.8.3 嵌套的数组
当我们创建数组的数组时,数组分配和引用的一般原则也是成立的。例如:
int A[5][3]
等价于
typedef int row3_t[3]; row3_t A[5];
公式一:
L
是数据类型T
以字节为单位的大小。
示例:
假设A[5][3]
A in %rdi, i in %rsi, j in %rdx
leaq (%rsi, %rsi, 2), %rax //Compute 3i
leaq (%rdi, %rax, 4), %rax //Compute xA+12i
movl (%rax, %rdx, 4), %eax //Read from M[xA+4(3i+j)]
示例:
3.8.4 定长数组
C语言编译器能够优化定长多为数组上的操作代码。
假设定义如下数组:
#define N 16
typedef int fix_matrix[N][N];
示例:
3.8.5 变长数组
假设变长数组的声明如下:
int A[expr1][expr2]
它可以作为一个局部变量,也可以作为一个函数的参数;通常对表达式expr1和expr2求值来确定数组的维度。例如访问 n x n
数组的元素 i , j ,可以写如下函数:
int var_ele(long n, int A[n][n], long i, long j){
return A[i][j];
}
参数 n 必须在参数 A[n][n] 之前。
如下代码,计算两个 *n x n * 矩阵 A 和 B 乘积的元素 i, k。
汇编代码如下
Registers: n in %rdi, Arow in %rsi, Bptr in %rcx
4n in %r9, result in %eax, j in %edx
.L24:
movl, (%rsi, %rdx, 4), %r8d ;Read Arow[j]
imull (%rcx), %r8d ;Multiply by *Bptr
addl %r8d, %eax ;Add to result
addq $1, %rdx ;j++
addq %r9, %rcx ;Bptr += n
cmpq %rdi, %rcx ;Compare j:n
jne .L24