不同系统下数据类型长度不一样
Data Type | ILP32(32位linux) | ILP64 | LP64(64位linux) | LLP64(64位windows) |
---|---|---|---|---|
char | 8 | 8 | 8 | 8 |
short | 16 | 16 | 16 | 16 |
int | 32 | 64 | 32 | 32 |
long | 32 | 64 | 64 | 32 |
long long | 64 | 64 | 64 | 64 |
pointer | 32 | 64 | 64 | 64 |
基本概念
许多计算机系统对基本数据类型合法地址做出了一些限制,要求某种类型对象的地址必须是某个值K(通常是2,4或8)的倍数。这种对齐限制简化了形成处理器和存储器系统之间的接口的硬件设计。对齐跟数据在内存中的位置有关。如果一个变量的内存地址正好位于它长度的整数倍,就被称做自然对齐。
为什么要字节对齐
CPU访问数据的效率。
如何处理字节对齐
编译器的规则:
- 数据类型自身对齐值:为指定平台上基本类型的长度。
- 结构体或者类的自身对齐值:为成员中自身对齐值最大的那个值。
- 指定对齐值:#pragma pack(value)。
- 数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中较小的值。
对于标准数据类型,它的地址只要是其长度的整数倍即可。非标准数据类型的原则:
- 数组:按照基本数据类型对齐,第一个对齐了后面的自然也对齐了。
- 联合:按其包含的长度最大的数据类型对齐。
- 结构体:结构体中每个数据类型都要对齐。
字节对齐的隐患
比如在强制类型转换的时候:
unsigned int i = 0x12345678;
unsigned char *p = NULL;
unsigned short *p1 = NULL;
p = &i;
*p = 0x00;
p1 = (unsigned short *)(p + 1);
*p1 = 0x0000;
最后两句代码,从奇数边界去访问unsigned short型变量,显然不符合对齐的规则。
如何查找与字节对齐方面的问题
如果出现对齐或者赋值问题首先查看:
- 编译器的大小端设置
- 体系是否支持非对齐访问
- 若支持看设置了对齐与否,如果没有则看访问时需要加某些特殊的修饰来标志其特殊访问操作
https://blog.youkuaiyun.com/cclethe/article/details/79659590