数据模型 (LP32 ILP32 LP64 LLP64 ILP64 )

本文探讨了不同操作系统下的数据模型,特别是32位与64位环境下C/C++类型的大小差异。通过示例代码展示了Windows与Linux平台下int、long及指针等基本类型的不同表现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自: http://blog.youkuaiyun.com/foreverfresh/article/details/6731785


32位环境涉及"ILP32"数据模型,是因为C数据类型为32位的int、long、指针。而64位环境使用不同的数据模型,此时的long和指针已为64位,故称作"LP64"数据模型。

现今所有64位的类Unix平台均使用LP64数据模型,而64位Windows使用LLP64数据模型,除了指针是64位,其他基本类型都没有变。

 TYPE                LP32     ILP32     LP64      ILP64      LLP64

CHAR                8             8             8             8                 8

SHORT             16         16            16           16             16

INT                    16          32            32           64             32

LONG               32          32            64           64             32

LONG LONG   64          64            64           64             64

POINTER          32         32            64           64             64


1> 平台: VS2010 + window7(64位系统)
                   GCC (4.4.6) + Redhat 6.3 (64 位系统)
 
2> VS2010默认生成32位的程序,设置VS2010 ,使其编译出64位程序
   
3> 代码:

int main()
{
printf("sizeof(char *) = %ld\n", sizeof(char *));            //result = 8;

printf("sizeof(long long) = %ld\n", sizeof(long long));  //result = 8;

printf("sizeof(long) = %ld\n", sizeof(long));                   // windows result = 4, but  linux result = 8
return 0;
}


4> VS2010 输出结果是     8 , 8, 4
      linux GCC 输出结果是 8, 8, 8
<think>好的,我需要解释一下“long 的不确定性”,特别是为什么在Windows的LLP64模型下是32位,而在Linux/macOS的LP64模型下是64位。首先,我得回顾一下不同系统的数据模型,以及它们如何处理基本数据类型的大小。 用户之前已经问过关于32位有符号整数的问题,之前的回答提到了不同系统下long类型的不确定性。现在用户特别针对这一点,希望更详细地了解为什么long在不同系统中有不同的位数。我需要确保回答准确,同时避免重复之前的内容,但可能需要补充更多背景知识。 首先,我应该明确什么是数据模型,比如ILP32LP64LLP64这些术语的含义。然后解释不同操作系统采用这些模型的原因,以及这对long类型的影响。需要指出Windows使用LLP64,所以long保持32位,而Linux和macOS使用LP64,所以long是64位。这可能涉及到历史原因和兼容性的考虑。 另外,需要说明C/C++标准中对long类型的规定,标准只规定了最小大小(至少32位),但具体实现由编译器和系统决定。因此,跨平台开发时依赖long类型可能导致问题,这就是为什么推荐使用固定宽度类型如int32_t或int64_t的原因。 还要考虑用户可能的疑问,比如为什么Windows选择LLP64而其他系统选择LP64。这涉及到在64位转型时保持向后兼容性的不同策略。例如,Windows可能希望保持long和int均为32位,以避免现有代码中数据类型大小的变化带来的问题,而Unix-like系统选择将long扩展为64位以利用更大的地址空间。 可能需要举一些例子,比如在代码中声明long变量,在不同系统下sizeof(long)的结果不同,这会导致数据存储或计算时的意外行为。同时,强调在需要确定大小时应使用stdint.h中的类型,而不是依赖原生的long。 还要检查是否有错误,比如LP64中long和指针都是64位,而LLP64中long long和指针是64位,但long仍然是32位。这可能需要用表格来对比不同数据模型下的类型大小,帮助用户更直观地理解。 最后,总结为什么这种不确定性存在,以及开发者应如何应对,比如使用可移植的类型,避免直接依赖long的特定大小,特别是在跨平台项目中。</think>在 C/C++ 中,`long` 类型的位数因 **系统数据模型**(Data Model)的不同而变化,导致其大小不确定。以下是关键原因和具体表现: --- ### **1. 数据模型的定义** 数据模型规定了基本类型(如 `int`、`long`、指针)的位数。常见模型包括: | 数据模型 | 系统典型代表 | `int` | `long` | 指针 | `long long` | |-------------|-----------------------|-------|--------|-------|-------------| | **ILP32** | 32 位系统(旧版) | 32 位 | 32 位 | 32 位 | 64 位 | | **LP64** | Linux/macOS(64 位) | 32 位 | **64 位** | 64 位 | 64 位 | | **LLP64** | Windows(64 位) | 32 位 | **32 位** | 64 位 | 64 位 | --- ### **2. `long` 的不确定性表现** - **Windows(LLP64 模型)** - `long` **固定为 32 位**,与 `int` 大小相同。 - 原因:保持与旧版 32 位代码的兼容性,避免因 `long` 位数扩大导致结构体对齐、API 参数传递等问题。 - 示例: ```c sizeof(long) = 4; // 4 字节(32 位) ``` - **Linux/macOS(LP64 模型)** - `long` **扩展为 64 位**,与指针大小一致。 - 原因:充分利用 64 位地址空间,简化指针与整型的转换(如 `void*` ↔ `long`)。 - 示例: ```c sizeof(long) = 8; // 8 字节(64 位) ``` --- ### **3. 为什么标准允许这种差异?** - **C/C++ 标准规定**: `long` 至少为 **32 位**,但具体位数由实现(编译器+系统)决定。 - 灵活性:允许不同系统根据硬件特性优化类型大小。 - 历史兼容性:早期系统(如 16 位机)中 `long` 可能仅为 32 位,而现代系统可扩展它。 --- ### **4. 实际影响** - **跨平台代码风险** ```c // 假设在 Windows 上开发: long buffer_size = 4 * 1024 * 1024 * 1024; // 值 = 4294967296(32 位 long 溢出!) ``` - 在 Windows 上,此代码会因 `long` 为 32 位导致溢出;在 Linux 上则正常。 - **结构体对齐问题** ```c struct Data { int a; long b; // Windows: 4 字节;Linux: 8 字节 }; ``` - 跨平台传输二进制数据时,结构体内存布局差异会导致解析错误。 --- ### **5. 解决方案** - **避免直接依赖 `long`** 需明确位数时,使用标准固定宽度类型: ```c #include <stdint.h> int32_t a; // 精确 32 位(有符号) int64_t b; // 精确 64 位(有符号) ``` - **兼容性写法** ```c #if defined(_WIN32) typedef int32_t platform_long_t; // Windows 的 long 是 32 位 #else typedef int64_t platform_long_t; // Linux/macOS 的 long 是 64 位 #endif ``` --- ### **总结** - `long` 的不确定性源于不同系统对 **数据模型的选择**(LP64 vs. LLP64)。 - Windows 的 LLP64 模型优先保证兼容性,Linux/macOS 的 LP64 模型追求性能和地址空间扩展。 - 编写跨平台代码时,应使用 `<stdint.h>` 中的明确类型(如 `int32_t`/`int64_t`),而非依赖 `long`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值