C语言_结构体 _ 字节对齐 - 详解
0 . 说明
看滴水逆向视频总结笔记
编译器VC++6.0
1.结构体__字节对齐的背景(本质)
由于我们32位的计算机在处理数据时最喜欢4个字节4个字节的处理,这样效率最高,所以在堆栈中,是4个字节一排,方便计算机每次处理4个字节。
本机宽度:4个字节
但是结构体在堆栈中分配一个连续的空间,一般会不等宽(char型数据一个字节,int型数据4个字节)。
设想一下:在堆栈的一排4个字节中,先为char分配一个空间,那int型数据占后面三个字节+下一排的一个字节。这样在堆栈分配空间时,的确是最省空间的,数据全挨在一起。
这种情况下,计算机要想调用这个int型数据,就要用两个堆栈地址。但是计算器为了提高效率,为了给这个int型数据 在堆栈中分配一个完整连续且在同一排的4字节空间,那么int型数据就不会占用第一排char型数据剩下的3个字节,而占用下一排完整的4个字节。
那这个char型数据在堆栈中占据的那一排空间就会空出3个字节,让一个char型数据占了4个字节,这就是
字节对齐
,这里是4字节对齐
所以,字节对齐
的本质就是:作为计算机本身,是想要空间还是要效率?显然在对于处理结构体这样特定的数据时,就会选择效率。
2.结构体__字节对齐的处理方式总结
结构体的一个成员先占领一个堆栈空间,如果在这一排中剩下字节如果不能满足下一个成员的大小,那么下一个成员就会在下一排堆栈空间存放数据。
如果能满足下一个成员的大小的情况下,两者大小不到四的话,小的一方补齐字节,平均分配这一排堆栈4个字节。
3.4字节对齐
__实例展示
这里就用vc的内存演示,因为内存和堆栈本质上是一致的。
a.发生字节对齐
总共为其分配了0xc个空间,但这四个成员的总体宽度只有8个字节。
第一个成员stu.a发生字节对齐
,char型数据占了4个字节。
第三个成员stu.c也发生字节对齐
,char型数据占2个字节。
b.改变书写顺序
我们发现,同样成员的结构体,因为书写顺序不同,这里就这分配了8个内存空间,两排堆栈[ebp-8]、[ebp-4]正好满满当当存放着4个成员,并没有发生字节对齐
c.体会
学会了字节对齐
的概率后,发现不同的书写也会造成不同的空间分配,为减少不必要的浪费,即有效率同时节省空间,我们在书写的时候,一定要考虑字节对齐
,合理安排书写顺序。
4.拓展
以上将的字节对齐
全是基于4字节对齐
,除此之外还有1字节对齐
,2字节对齐
,8字节对齐
和16字节对齐
,
字节对齐
是向下兼容的,也就是说,会自动适配结构体成员的宽度大小,选择最大的作为字节对齐
的模式,
一般VC++6.0是默认8字节对齐
,而我们上述写的结构体中,宽度最大的成员是int型数据4个字节,所以自动适配按照4字节对齐
。
右键项目文件->setting->C/C+±>Code Generation->Stuct menber alignment
默认是8字节,可以更改,但是不建议更改。
5.8字节对齐
实例展示
可以发现
-
8字节对齐
的方式,在内存空间中都是8个字节为一个整体。 -
8字节对齐
在4字节对齐
的基础上,以8个字节为整体。 -
double型数据占8个字节,在内存中分别以两个4字节储存
例如:
6.强制转换 个别结构体 字节对齐的方式
#pragma pack(n)//n代表字节对齐的方式n = 1、2、4、8、16.
struct student
{
char a;
int b;
};
#pragma pack()
如果有有什么不懂或是我那个地方写的不对、不好的话,欢迎大家留言指正