不同系统下C语言类型长度
Data Type | ILP32 | ILP64 | LP64 | LLP64 |
---|---|---|---|---|
char | 8 | 8 | 8 | 8 |
short | 16 | 16 | 16 | 16 |
int | 32 | 64 | 32 | 32 |
long | 32 | 64 | 64 | 32 |
float | 32 | 32 | 32 | 32 |
double | 64 | 64 | 64 | 64 |
long long | 64 | 64 | 64 | 64 |
pointer | 32 | 64 | 64 | 64 |
大部分64位Unix, Linux 使用的都是LP64模型,32位Linux使用ILP32模型,64位Windows使用LLP64模型。
LP64即 long、pointer 为64位,ILP64即 int、long、pointer为64位,ILP32 即 int、long、pointer为32位,LLP64即 long long、pointer为64位。
字节对齐
字节对齐的细节和具体编译器实现相关,对于标准数据类型,其地址只需要为其长度的整数倍。其他数据类型,数组按照基本数据类型对齐,union按照其包含长度最大的数据类型对齐,当数据类型为结构体时,一般而言满足三个准则:
- 结构体变量的首地址能够被其最宽基本类型成员的大小所整除
- 结构体每个成员对于结构体首地址的偏移量都是成员大小的整数值,如有需要,编译器会在成员之间加上填充字节
- 结构体的总大小为结构体最宽基本类型成员大小的整数倍。如有需要,编译器会在最末一个成员之后加上填充字节。
一个例子,定义如下的一个结构体
1 | struct Test |
输出结构体的大小,每一个成员的地址,结果如下:
1 | size of int: 4 |
可以看出,int 和 double 的地址相差了8个字节,而为了使得结构体的大小为最宽成员大小的整数倍,编译器在float后面添加了4个字节。
当修改结构体为如下格式时:
1 | struct Test2 |
结构体对应的大小及地址如下:
1 | size of Test2: 16 |
可以看出,编译器没有添加填充字节,结构体的大小等于三个成员大小之和。
字节对齐的原因
保证CPU访问数据的效率。如果一个处理器每次能从存储器中读取8个字节,当一个double类型的数据地址为8的倍数时,就可以保证每次都能读取出这个double。否则,需要执行多次存储器访问,因为对象可能被分放在两个8字节存储块中。