一直感觉机组老师讲课特别棒,学习完编程语言底层的一些机制之后,感觉对数组指针和结构体的理解更透彻了,趁着还没有忘记先记录下来。
数组
一维数组
一个维度的数组在内存中是连续存储的,一个T arr[N]
的数组长度可表示为:N*sizeof(T)
。
我们在编程的时候,经常用数组名当做指针来使用,进而方便访问数组中的元素,例如我们有个数组int val[5]={1,5,2,1,3};
,这个数组名的相关属性举例如下(int类型变量4字节):
下面看一下汇编层面如何实现数组相关操作的,我们假设有这样几个数组:
#define ZLEN 5
typedef int zip_dig[ZLEN];
zip_dig tju = { 1, 5, 2, 1, 3 };
zip_dig nku = { 0, 2, 1, 3, 9 };
zip_dig pku = { 9, 4, 7, 2, 0 };
我们想要实现下面的查询函数和遍历函数:
int get_digit(zip_dig z, int digit)
{
return z[digit];
}
void zincr(zip_dig z) {
int i;
for (i = 0; i < ZLEN; i++)
z[i]++;
}
查询函数的汇编代码如下:
# %rdi = z
# %rsi = digit
movl (%rdi,%rsi,4), %eax
# z[digit]
遍历函数的汇编代码如下:
# %rdi = z
movl $0, %eax # i = 0
jmp .L3 # goto middle
.L4: #loop:
addl $1, (%rdi,%rax,4) # z[i]++
addq $0, %eax # i++
.L3:
cmpq $4,%rax # 4-i
jbe .L4 # if <= ,goto loop
rep;ret
另外值得注意的:在我们声明某个数组的作用域内,如果使用sizeof(arr)
函数,会返回整个数组所占用的空间,但是如果我们把这个数组传递到另外一个函数中或者超过这个作用域,此时在此使用sizeof(arr)
函数,sizeof(arr)
会把arr
当做一个普通的指针变量来处理,举例代码如下:
#include <iostream>
void SeeSizeof(int* arr){
std::cout << "M被传递进参数之后:" << sizeof(arr) << std::endl;
}
int main(int argc, char const *argv[])
{
int N = 8;
int arr[N]={1,2,3,4,5,6,7,8};
for (auto& d:arr)
std::cout << d << std::endl;
std::cout << "M未被传递进参数之前:" << sizeof(arr) << std::endl;
SeeSizeof(M);
return 0;
}

多维数组
。。。
待续
多层数组
。。。
结构体
。。。
联合体
。。。