首先在C语言中,结构体占用的是一片连续的内存空间
对齐原因
1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
以前对于内存对齐的计算理解错了,今天看见一个视频幡然醒悟。
以下面的结构体为例:
struct stu { char *p; //4 char arr[2]; //2 → 4+2+2(补)=8 int c; //4 short d; //2 → 4+2+2(补)=8 double f; //8 long g; //4 → 4+4(下面 float h[2] 中取一个刚好可以凑足 8 个字节)=8 float h[2]; // 4(上面拿走了一个)+4(补)=8 }stu;
内存对齐规则:以结构体中占用字节数最大的修饰变量的关键字为基准进行对齐。
在 stu 中(32位操作系统):首先占用内存最大的关键字为 double 占 8 个字节。
以此为基准对齐,从头开始看。指针 p 占四个字节,arr 占 1*2 = 2个字节,共 6 个字节,不足 8 位,c 占4个字节,如果接着加上前面的就超出了 8 字节的基准,所以 先对前面的 6 个字节进行补齐(6+2 = 8),再看 c 的下一个 d 占2个字节,同样的 4+2 = 6 未超出 8,所以看 double f,超出了,所以前面的 c 和 d占用字节为(4+2 = 6 → 6+2 = 8);f 刚好 8 个字节;继续看 g,占用 4 个字节,不足 8 ,因为 h是个含两个 float 类型的数组,一个 float 刚好占四个字节,所以拿一个与前面的 g 相加,最后只剩一个 float 类型的数据,占 4 个字节,不足 8,所以补 4.(4+4 = 8);
所以: 4(char *p)+ 2(char arr[2])+ 2(补)= 8;
4(int c) + 2(short d)+ 2(补)= 8;
8(double)
4(long g)+ 4(float h[1])= 8;
4(float h[1])+ 4(补) = 8;
共占 40个字节。