在C语言中,使用sizeof运算符计算结构体的大小时,得到的结果是对齐之后占用的字节数,而非成员变量实际长度的简单相加。这是因为编译器会根据平台的对齐规则,在成员之间或结构体末尾插入填充字节,以优化内存访问效率。
C语言结构体对齐规则:
结构体(struct)的数据成员,第一个数据成员存放的地址为结构体变量偏移量为0的地址处.
其他结构体成员自身对齐时,存放的地址为min{有效对齐值为自身对齐值, 指定对齐值} 的最小整数倍的地址处.
注:自身对齐值:结构体变量里每个成员的自身大小
注:指定对齐值:有宏 #pragma pack(N) 指定的值,这里面的 N一定是2的幂次方.如1,2,4,8,16等.如果没有通过宏那么在32位Linux主机上默认指定对齐值为4,64位的默认对齐值为8,AMR CPU默认指定对齐值为8;
注:有效对齐值:结构体成员自身对齐时有效对齐值为自身对齐值与指定对齐值中 较小的一个.
总体对齐时,字节大小是min{所有成员中自身对齐值最大的, 指定对齐值} 的整数倍.
#pragma pack(N) 每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。
详细解释
-
对齐规则:
-
每个成员的偏移量必须是其类型大小(或编译器指定的对齐值)的整数倍。
-
整个结构体的大小必须是其最大成员大小的整数倍(末尾可能填充)。
-
成员的顺序会影响填充字节的数量。
-
-
编译器行为:
-
编译器会插入“填充字节”(Padding)以满足对齐要求。
-
默认对齐值通常由目标平台决定(如32位系统通常按4字节对齐)。
-
示例说明
示例1:成员顺序影响结构体大小
#include <stdio.h>
struct Example1 {
char a; // 1字节
int b; // 4字节
char c; // 1字节
};
struct Example2 {
char a; // 1字节
char c; // 1字节
int b; // 4字节
};
int main() {
printf("Example1 大小: %zu\n", sizeof(struct Example1)); // 输出 12
printf("Example2 大小: %zu\n", sizeof(struct Example2)); // 输出 8
return 0;
}
-
Example1 的内存布局:
-
char a占1字节。 -
填充3字节(为了对齐
int b到4字节)。 -
int b占4字节。 -
char c占1字节。 -
末尾填充3字节(使总大小为最大成员
int的整数倍)。 -
总计:1 + 3 + 4 + 1 + 3 = 12字节。
-
-
Example2 的内存布局:
-
char a和char c共占2字节。 -
填充2字节(为了对齐
int b到4字节)。 -
int b占4字节。 -
总计:2 + 2 + 4 = 8字节。
-
示例2:结构体末尾填充
struct Example3 {
short a; // 2字节
int b; // 4字节
};
int main() {
printf("Example3 大小: %zu\n", sizeof(struct Example3)); // 输出 8
return 0;
}
-
Example3 的内存布局:
-
short a占2字节。 -
填充2字节(为了对齐
int b到4字节)。 -
int b占4字节。 -
总计:2 + 2 + 4 = 8字节。
-
关键结论
-
sizeof的结果是对齐后的总大小,包含填充字节。 -
成员顺序和类型大小直接影响结构体大小。
-
可通过调整成员顺序或使用编译指令(如
#pragma pack)优化内存占用。
提示:若想减少填充字节,可将相同类型的成员连续声明,或手动控制对齐方式(但需谨慎,可能影响性能)。
1万+



被折叠的 条评论
为什么被折叠?



