LP32,ILP32,LP64,LLP64,ILP64数据模型
在32位和64位平台上,float
都是 4 字节,double
都是 8 字节;(C中直接写小数,默认是double
型)
LP64、LLP64 和 ILP64这三个 64 位数据模型之间的区别仅在于非浮点数据类型(long
, long long
, pointer
)。
32位环境涉及"ILP32"数据模型,是因为C数据类型为32位的int、long、指针。而64位环境使用不同的数据模型,此时的long和指针已为64位,故称作 “LP64” 数据模型。
现今所有64位的类Unix平台均使用 LP64 数据模型,而64位Windows使用 LLP64 数据模型,除了指针是64位,其他基本类型都没有变。
Data Type | ILP32 | LP32 | ILP64 | LP64 | LLP64 |
---|---|---|---|---|---|
宏定义 | - | - | - | __LP64__ | __LLP64__ |
平台 | Win32 API / Unix 和 Unix 类的系统 (Linux,Mac OS X) | Win16 API | Unix 和 Unix 类的系统 (Linux,Mac OS X) | Win64 API | |
char | 8 | 8 | 8 | 8 | 8 |
short | 16 | 16 | 16 | 16 | 16 |
int | 32 | 16 | 64 | 32 | 32 |
long | 32 | 32 | 64 | 64 | 32 |
long long | 64 | 64 | 64 | 64 | 64 |
pointer | 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 位的。
当一个或多个 C 数据类型的宽度从一种模型变换成另外一种模型时,应用程序可能会受到很多方面的影响。这些影响主要可以分为两类:
- 数据对象的大小。编译器按照自然边界对数据类型进行对齐;换而言之,32 位的数据类型在 64 位系统上要按照 32 位边界进行对齐,而 64 位的数据类型在 64 位系统上则要按照 64 位边界进行对齐。这意味着诸如结构或联合之类的数据对象的大小在 32 位和 64 位系统上是不同的。
- 基本数据类型的大小。通常关于基本数据类型之间关系的假设在 64 位数据模型上都已经无效了。依赖于这些关系的应用程序在 64 位平台上编译也会失败。例如,sizeof (int) = sizeof (long) = sizeof (pointer) 的假设对于 ILP32 数据模型有效,但是对于其他数据模型就无效了。
总之,编译器要按照自然边界对数据类型进行对齐,这意味着编译器会进行 “填充”,从而强制进行这种方式的对齐,就像是在 C 结构和联合中所做的一样。结构或联合的成员是根据最宽的成员进行对齐的。