指针与内存对齐到底是什么鬼?( 五 )


结构体(首字节地址)必须是最大成员变量数据类型的整数倍的证明
可以由2.推导而来 。步骤是:
1、假设结构体中的最大成员变量的长度是long8个字节;那么,根据2.可知,这个变量前面的变量的长度总和,必须是8的整数倍;
2、所以,如果结构体的首字节地址不是8的整数倍,那么就算最大成员变量之前的所有成员变量长度和满足了是8的整数倍,也不能保证2.的成立;
3、所以结构体的首字节地址必定是最大成员长度的整数倍,也就是8字节对齐的 。

指针与内存对齐到底是什么鬼?

文章插图
内存布局
结构体的总体长度必须是最大成员变量类型长度的整数倍证明
这个主要是考虑数组的情况 。在单个结构体中对齐的数据,必须在数组情况下也是对齐的,如果最大的成员变量是对齐的,则所有其他成员变量都是对齐的 。证明如下图:
指针与内存对齐到底是什么鬼?

文章插图
证明
以一个例子总结#include#includetypedef struct testint a; // 4// padding 4long long b; // 8 b要8字节对齐,也就是前面的字节数要是8的倍数,而前面只有4字节,所以要padding4个字节char c; // 1// padding 1short d; // 2 同样d前面的字节数要是2的倍数,所以padding 1个字节// padding 4 前面整体的test结构只有20个字节,而整体的大小也要是最大元素的整数倍,因为如果是数组,那么两个my的元素那么第二个my的b变量位于28的位置,不是8的整数倍,所以结尾再padding4个字节 。凑成24个字节 。} My;int main(int argc, char *argv[])//栈上分配My my;my.a = 1;11ab: c7 45 e0 01 00 00 00 movl $0x1,-0x20(%rbp)my.b = 2L;11b2: 48 c7 45 e8 02 00 00 movq $0x2,-0x18(%rbp)11b9: 00my.c = 'a';11ba: c6 45 f0 61 movb $0x61,-0x10(%rbp)my.d = 4;11be: 66 c7 45 f2 04 00 movw $0x4,-0xe(%rbp)My my;my.a = 1;my.b = 2L;my.c = 'a';my.d = 4;printf("size of my:%dn", sizeof(My));printf("address of my is:%xn", &my);//堆上分配11f8: bf 18 00 00 00 mov $0x18,%edi11fd: e8 8e fe ff ff call 10901202: 48 89 45 c0 mov %rax,-0x40(%rbp)my_on_heap->a = 1;1206: 48 8b 45 c0 mov -0x40(%rbp),%rax120a: c7 00 01 00 00 00 movl $0x1,(%rax)my_on_heap->b = 2L;1210: 48 8b 45 c0 mov -0x40(%rbp),%rax1214: 48 c7 40 08 02 00 00 movq $0x2,0x8(%rax)121b: 00my_on_heap->c = 'a';121c: 48 8b 45 c0 mov -0x40(%rbp),%rax1220: c6 40 10 61 movb $0x61,0x10(%rax)my_on_heap->d = 4;1224: 48 8b 45 c0 mov -0x40(%rbp),%rax1228: 66 c7 40 12 04 00 movw $0x4,0x12(%rax)My* my_on_heap = (My*)malloc(sizeof(My));my_on_heap->a = 1;my_on_heap->b = 2L;my_on_heap->c = 'a';my_on_heap->d = 4;printf("address of my is:%xn", my_on_heap);参考
视频——内存对齐到底是个什么鬼




推荐阅读