数据模型(LP32 ILP32 LP64 LLP64 ILP64 )
32位环境涉及"ILP32"数据模型,是因为C数据类型为32位的int、long、指针。而64位环境使用不同的数据模型,此时的long和指针已为64位,故称作"LP64"数据模型。
现今所有64位的类Unix平台均使用LP64数据模型,而64位Windows使用LLP64数据模型,除了指针是64位,其他基本类型都没有变。
TYPE LP32 ILP32 LP64 ILP64 LLP64CHAR 8 8 8 8 8SHORT 16 16 16 16 16INT 16 32 32 64 32LONG 32 32 64 64 32LONG LONG 64 64 64 64 64POINTER 32 32 64 64 64 在这张表中,LP64,ILP64,LLP64是64位平台上的字长模型,ILP32和LP32是32位平台上的字长模型。LP64意思是long和pointer是64位,
ILP64指int,long,pointer是64位,
LLP64指long long和pointer是64-bit的。
ILP32指int,long和pointer是32位的,
LP32指long和pointer是32位的。
float 都是4字节;
double 都是8字节;(C中直接写小数,默认是double型)
这 3 个 64 位模型(LP64、LLP64 和 ILP64)之间的区别在于非浮点数据类型。当一个或多个 C 数据类型的宽度从一种模型变换成另外一种模型时,应用程序可能会受到很多方面的影响。这些影响主要可以分为两类:
- 数据对象的大小。编译器按照自然边界对数据类型进行对齐;换而言之,32 位的数据类型在 64 位系统上要按照 32 位边界进行对齐,而 64 位的数据类型在 64 位系统上则要按照 64 位边界进行对齐。这意味着诸如结构或联合之类的数据对象的大小在 32 位和 64 位系统上是不同的。
- 基本数据类型的大小。通常关于基本数据类型之间关系的假设在 64 位数据模型上都已经无效了。依赖于这些关系的应用程序在 64 位平台上编译也会失败。例如,
sizeof (int) = sizeof (long) = sizeof (pointer)
的假设对于 ILP32 数据模型有效,但是对于其他数据模型就无效了。
总之,编译器要按照自然边界对数据类型进行对齐,这意味着编译器会进行 “填充”,从而强制进行这种方式的对齐,就像是在 C 结构和联合中所做的一样。结构或联合的成员是根据最宽的成员进行对齐的。
数据类型转换原则
结构体对齐,默认对齐原则:
1.数据类型对齐值: char型数据自身对齐值为1 short为2,int、float为4,double为8(windows) 解释: char变量只要有一个空余的字节即可存放 short要求首地址能被2整除 int、float、double同理2.结构体的对齐值: 其成员中自身对齐值最大的那个值。 解释: 结构体最终对齐按照数据成员中最长的类型的整数倍指定对齐原则:使用#pragma pack改变默认对其原则格式:#pragma pack (value)时的指定对齐值value。结构体最终对齐按照指定对齐值的整数倍注意:1.value只能是:1 2 4 8等2.指定对齐值与数据类型对齐值相比取较小值如:如果指定对齐值:设为1:则short、int、float等均为1设为2:则char仍为1,short为2,int 变为2
移位运算
左移<< 将一个数的二进制位左移,高位丢弃,低位补0 例:a = a<<2 将a的二进制数左移2位,右补0 若a=15,即二进制数0 0 0 01111 左移2位得0 011110 0,(十进制数60)>>算术右移 有符号数,如果为正数,则左边移入0,右边丢弃 如果为负数,左边移入1,右边丢弃>>逻辑右移 不关心正数、负数,左边均移入0,右边丢弃 算术或者逻辑右移,由编译器决定
博主今天在写代码的时候遇到一个奇怪的问题,程序的要求是实现一个int的移位操作,不管左移还是右移,空出来的位置通通置0即逻辑移位。一开始没注意太多直接用了<<和>>移位操作符,结果却发现实现是错误的==!
经过查证发现,c语言中的移位操作符,在左移时执行的是逻辑移位,在右移时执行的是算术移位。那怎么用>>实现右移操作呢? 又经过查证得知,无符号数的移位操作都是执行的逻辑移位。那么要想用>>实现逻辑右移就可以将操作数强制类型转化为unsigned类型,如下:int a = 0xfffffffe;
int b = (unsigned int)a >> 1; 执行的结果是2147483647即7fffffff,可见其右移后左端补的是0。 综上:C语言中移位操作符实现的是逻辑左移和算术右移,但是算术左移和逻辑左移的效果相同,算术右移和逻辑右移的效果不同,要实现逻辑右移可将操作数强制类型转化为无符号数