C编程-字节对齐(上)讲到系统会对结构体进行默认字节对齐,当然也可以人为设定对齐方式,下面针对两种方式进行描述。
方式一、
通过#pragma指令对结构体设定对齐方式,如下:
#pragma pack(push, 1) // 将原有对齐方式压栈,并设置新的对齐方式
typedef struct test{
char a;
int b;
char c;
double d;
}TEST;
#pragma pack(pop) // 恢复原有对齐方式
上述示例如果未使用#pragma指令,其结构体大小是24字节,通过指定1字节对齐,其结构体最终大小则是14字节。
该方式尤其需要注意后面的恢复操作,否则包含该头文件之后的头文件,结构体字节对齐方式都会受影响。
方式二、
通过__attribute__((aligned(n)))设置类型属性,如下:
struct test {
char a;
short b;
}__attribute__((aligned(8)));
该结构体sizeof获取的大小是8字节。
__attribute__((aligned(n)))修改的是结构体最终需8字节对齐,内部变量对齐方式没变,即变量a占用1个字节,其后填充1个字节,变量b占用2个字节,其后填充4个字节。
如果结构体最大成员变量所占字节数大于n,则仍旧按最大成员变量长度对齐。 即如果上面是aligned(1),则结构体大小是4字节。
需要注意如下两种情况:
typedef struct testa {
char a;
short b;
}__attribute__((aligned(8))) TESTA;
typedef struct testb {
char a;
short b;
}TESTB __attribute__((aligned(8))) ;
TESTA和TESTB结构体的大小是不一样的,前者大小是8字节,而后者大小是4字节,因为前者__attribute__设置的属性针对的是结构体,而后者__attribute__设置的属性针对的是TESTB变量声明,即TESTB声明的变量需要8字节对齐,这就会存在如果声明TESTB变量类型数组,则会出现如下错误:
alignment of array elements is greater than element size
因为其结构体本身只有4字节,却要8字节对齐。
通过__attribute__((packed))设置类型属性,该选项取消编译器对结构体的优化操作,按实际字节数占用地址空间,如下:
struct test {
char a;
short b;
}__attribute__((packed));
得到的结构体大小就是3字节。
在了解了手动对齐的方式后,那一般什么情况下会需要手动设置对齐方式呢?
人为修改对齐方式,一般常见的就是修改成1字节对齐,这样修改的其中一点作用就是结构体占用的存储空间变小了,但读取效率上肯定会受影响。
另外常见的场景就是两方主机进行协议通信,其定义的协议结构体字段,不希望因为不同CPU可能处理字节对齐方式不同而有所差异,通过修改成1字节对齐,保证传输两方变量都是一一对应上的。
推荐阅读:
https://www.cnblogs.com/clover-toeic/p/3853132.html
https://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Type-Attributes.html#Type-Attributes