面试:结构体默认是对齐的嘛?如何禁止对齐?
是的。
结构体默认是对齐的。结构体对齐是为了优化内存访问速度和减少CPU访问内存时的延迟。结构体对齐的规则如下:
-
某数据类型的变量存放的地址需要按有效对齐字节剩下的字节数可以被该数据类型所占字节数整除,char可以放在任意位置,int存放在剩下字节数可以被4整除的位置。这个对齐规则是内部一定的
-
结构体的大小一定要为有效对齐值的整数倍
-
当没有明确指明时,以结构体中最长的成员的长度来对齐,注意!数组成员个数并不影响有效对齐值,只是数组类型大小和其他成员比较取最大。但是当然数组成员总占用内存也要遵循字节对齐
-
当用#pragma pack(n)指定时,以n和最长成员中长度较小的值来对齐。
比如:
#include <iostream>
struct {
char a;
int b;
}aa;
int main()
{
std::cout << sizeof(aa)<<std::endl;
}
结果输出是8。
禁止自动对齐:
#pragma pack(1) 将对齐设置为1字节,这意味着所有的成员变量都将按照1字节对齐,不会有任何填充字节。这在处理网络协议或文件格式时非常有用,因为它可以确保结构体的布局与协议或文件格式严格匹配。
#pragma pack(1)
struct TCPHEADER
{
short SrcPort; // 16位源端口号
short DstPort; // 16位目的端口号
// ... 其他成员变量
};
#pragma pack()
相比之下,#pragma pack(push, 1) 不仅将当前的对齐设置为1字节,还将之前的对齐设置压入一个内部堆栈。这样,当你使用 #pragma pack(pop) 时,可以恢复到之前的对齐设置。这在你只想临时改变对齐设置的情况下非常有用,因为它允许你在代码的不同部分使用不同的对齐策略,而不会影响全局的对齐设置。