- 编译器版本(
MinGW及其衍生品,比如TDM-GCC可能不支持#pragma pack(n), n>1,参见 mingw-and-packed-struct-alignment-using-c11)
1
2
3
4
5 ❯ gcc --version
gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- 本文讨论的对齐属性
1
2
3
__attribute__((packed));
__attribute__((aligned(8)));
- 完整验证代码见文末
- 在 Linux 环境下
char占 字节,int占 字节,short占 字节,long long占 字节(long占 字节( 位), 字节( 位))
实验 1·
无全局的
#pragma pack(n)
实验结果如下
1 | struct test { // size = 15 |
注释中所标注的是结构体中每个成员变量所占内存空间的大小(如 位与 位结果不同,左侧为 位下运行结果)
- test:
__attribute__((packed))取消字节对齐,所有成员紧凑排列; - test1: 系统中,默认 字节对齐,则
char后填充 字节,short后填充 字节,总共占 字节; 位系统中,为了保证long long字节对齐,要在short后填充 字节,总共占 字节; - test2:
__attribute__((aligned(8)));要求test2的起始地址是 的倍数。- 位系统中,按照
test1,结构体总共占 字节。但考虑连续实例化test2的情况,第一个起始地址是 的倍数,占 字节,下一个的起始地址就不再是 的倍数,因此需要在末尾再填充 字节,总共占用 字节;- 位系统中,按照
test1,结构体总共占 字节。可以满足再实例化的结构体起始地址是 的倍数,不需要在末尾额外填充,总共占用 字节;
- 位系统中,按照
- 位系统中,按照
实验 2·
1
实验结果如下
1 | struct test { // size = 15 |
全局的 #pragma pack(1) 表示默认紧凑排列,所以 test 和 test1 均占用 15 字节。
test2 中 __attribute__((aligned(8))); 要求起始地址 字节对齐,需要在末尾额外填充 字节,总共占 字节。
实验 3·
1
实验结果如下
1 | struct test { // size = 15 |
全局的 #pragma pack(2) 表示默认按 字节对齐排列,
- test:
__attribute__((packed))取消字节对齐,所有成员紧凑排列; - test1:按 字节对齐,则
char后需填充 字节,总共占 字节; - test2:按
test1,总共占 字节,可以满足再实例化的结构体起始地址是 的倍数,不需要在末尾额外填充,总共占 字节;
附录:完整实验代码·
1 |
|
讨论
评论