C语言结构体字节对齐问题
文章目录
这篇文章介绍C语言结构体字节对齐的问题。
1 结构体字节对齐的规则
-
结构体变量的首地址能够被其最宽基本类型成员的大小所整除;???
-
数据类型自身的对齐:例如,在x86_64系统,char型数据自身对齐值为1字节,short型数据为2字节,int/float型为4字节,long/double/void*型为8字节。
-
结构体或者类的自身的对齐:其成员中自身对齐值中的最大值。
-
指定对齐值的情况下的对齐规则:#pragma pack (value)时的指定对齐值value。指定规则后以指定规则进行对齐。
- 使用伪指令#pragma pack(n):C编译器将按照n个字节对齐;
- 使用伪指令#pragma pack(): 取消自定义字节对齐方式。
-
数据成员、结构体和类的有效对齐值:若存在指定对齐值,需要自身对齐值和指定对齐值中较小者,即有效对齐值=min{自身对齐值,当前指定的pack值}。
2 x86环境各种基本数据类型的字节数
数据类型 | x86 | x86_64 |
---|---|---|
char | 1 | 1 |
short | 2 | 2 |
int | 4 | 4 |
long | 4 | 8 |
float | 4 | 4 |
double | 8 | 8 |
void* | 4 | 8 |
3 示例程序
当前的实例程序假定结构体首地址为0。环境关键信息如下:
-
Archithecture: x86_64
-
GCC version: 4.4.7
3.1 指定1字节对齐的示例分析
|
|
说明:
变量a,char自身对齐值为1, 指定值为1; 两者取小的值为1。首地址为0,变量a是对齐的,因此变量a占用1个字节。此时偏移1字节。
变量b, int类型自身对齐值为4, 指定值为1,两者取小的偏移值为1。当前偏移1字节,因此变量b前不需要填充,b占用4字节。此时偏移5字节。
变量c, short类型自身对齐值为2,指定值为1,两者取小的偏移单位为1。当前偏移5字节,因此变量c前也不需要填充,c占用2字节。此时偏移7字节。
结构体自身的对齐值取最大变量的长度(int),即4字节。但是指定的长度为1字节,两者取小即可得到整个结构体的对齐单位为1字节。因此,整个结构体占用7字节。
3.2 指定2字节对齐的示例分析
|
|
说明:
变量a,char自身对齐值为1, 指定值为2; 两者取小的值为1。首地址为0,变量a是对齐的,因此变量a占用1个字节。此时偏移1字节。
变量b, int类型自身对齐值为4, 指定值为2,两者取小的偏移值为2。当前偏移1字节,因此变量b前需要填充1字节,b占用4字节。此时偏移6字节。
变量c, short类型自身对齐值为2,指定值为2,两者取小的偏移单位为2。当前偏移6字节,因此变量c前不需要填充,c占用2字节。此时偏移8字节。
结构体自身的对齐值取最大变量的长度(int),即4字节。但是指定的长度为2字节,两者取小即可得到整个结构体的对齐单位为2字节。当前偏移长度为8字节,已经是对齐单位整数倍,所以无需填充。因此,整个结构体占用8字节。
3.3 指定4字节对齐的示例分析
|
|
说明:
变量a,char自身对齐值为1, 指定值为4; 两者取小的值为1。首地址为0,变量a默认是对齐的,因此变量a占用1个字节,无需填充。当前偏移1字节。
变量b, int类型自身对齐值为4, 指定值为4,两者取小的偏移值为4。当前偏移1字节,因此变量b前需要填充3字节,b占用4字节。当前偏移8字节。
变量c, short类型自身对齐值为2,指定值为4,两者取小的偏移单位为2。当前偏移8字节,因此变量c前不需要填充,c占用2字节。当前偏移10字节。
结构体自身的对齐值取最大变量的长度(int),即4字节。指定的长度为4字节,两者取小即可得到整个结构体的对齐单位为4字节。当前偏移长度为10字节,不是对齐单位整数倍,所以需要填充2字节。因此,整个结构体占用12字节。
3.3 指定8字节对齐的示例分析
|
|
说明: 变量a,char自身对齐值为1, 指定值为8; 两者取小的值为1。首地址为0,变量a默认是对齐的,因此变量a占用1个字节,无需填充。当前偏移1字节。
变量b, int类型自身对齐值为4, 指定值为8,两者取小的偏移值为4。当前偏移1字节,因此变量b前需要填充3字节,b占用4字节。当前偏移8字节。
变量c, short类型自身对齐值为2,指定值为8,两者取小的偏移单位为2。当前偏移8字节,因此变量c前不需要填充,c占用2字节。当前偏移10字节。
结构体自身的对齐值取最大变量的长度(int),即4字节。指定的长度为8字节,两者取小即可得到整个结构体的对齐单位为4字节。当前偏移长度为10字节,不是对齐单位整数倍,所以需要填充2字节。因此,整个结构体占用12字节。
3.4 不指定字节,按照默认对齐的示例分析
|
|
说明: 变量a,char自身对齐值为1; 首地址为0,变量a默认是对齐的,因此变量a占用1个字节,无需填充。当前偏移1字节。
变量b, int类型自身对齐值为4。当前偏移1字节,因此变量b前需要填充3字节,b占用4字节。当前偏移8字节。
变量c, short类型自身对齐值为2。当前偏移8字节,因此变量c前不需要填充,c占用2字节。当前偏移10字节。
变量d, long类型自身对齐值为8。当前偏移10字节,因此变量d前需要填充6个字节,c占用8字节。当前偏移24字节。
结构体自身的对齐值取最大变量的长度(long),即8字节。无指定的对齐长度,因此整个结构体的对齐单位为8字节。当前偏移长度为24字节,是对齐单位整数倍,所以不需要填充。因此,整个结构体占用24字节。