Skip to content
编程开物
编程开物

一段代码,一段Prompt,一物成型。 探索编程、AI应用、架构设计与产品设计,分享工程实践,记录技术学习、工作总结与产品创造。

  • 首页
  • 编程基础
  • 数据与AI
    • 数据工程
    • AI基础理论
    • AI实践应用
  • 系统架构
    • 传统应用架构设计
    • AI应用架构设计
  • 项目管理
  • 产品设计
  • 技术教程
  • 行业动态
  • 编程笔记
  • 实用技巧
  • 关于我
编程开物

一段代码,一段Prompt,一物成型。 探索编程、AI应用、架构设计与产品设计,分享工程实践,记录技术学习、工作总结与产品创造。

C语言中为什么Win 64机器int和long类型是4个字节?

编码者, 2024年11月14日2024年11月14日

三位C/C++程序员走进了一家酒吧。第一位争辩说 sizeof(void*) 等于 sizeof(long),第二位争辩说 sizeof(void*) 等于 sizeof(int),第三位争辩说是 sizeof(long long)。与此同时,他们每个人都对,也都错(需要上关于可移植C代码的课)。这是怎么回事呢?

程序员在写“Hello, World!”后,可能写的第一个程序是这样的:

#include <stdio.h>
int main () {
  printf("sizeof(int): %zu\n", sizeof(int));
  printf("sizeof(long): %zu\n", sizeof(long));
  printf("sizeof(long long): %zu\n", sizeof(long long));
  printf("sizeof(void*): %zu\n", sizeof(void*));
}

注意使用了 %zu 格式说明符,这是C99新增的特性,但对于老编译器不一定兼容!(这篇文章更多是讨论将旧代码迁移到新机器时的考虑,而不是将新代码迁移到旧机器。没有标准兼容的C编译器会使得编写可移植的C代码更加困难,这也是另一个博客话题)。

当我在我的x86-64 OSX机器上运行这段代码时,得到的输出是:

sizeof(int): 4
sizeof(long): 8
sizeof(long long): 8
sizeof(void*): 8
看起来我就是故事中第一位程序员的情况,因为在我的机器上,sizeof(long) 等于 sizeof(void*)。还要注意,sizeof(long long) 也是相等的。

但如果我在一台32位机器上编译这段代码,会发生什么呢?幸运的是,我的处理器支持32位二进制的向后兼容,所以我可以在本地交叉编译并运行。示例:

➜  clang sizeof.c -Wall -Wextra -Wpedantic
➜  file a.out
a.out: Mach-O 64-bit executable x86_64
➜  clang sizeof.c -Wall -Wextra -Wpedantic -m32
➜  file a.out
a.out: Mach-O executable i386
➜  ./a.out
sizeof(int): 4
sizeof(long): 4
sizeof(long long): 8
sizeof(void*): 4

哇,突然间 sizeof(void*) 等于 sizeof(int) 等于 sizeof(long)!这似乎是故事中第二位程序员的情况。

第一位和第二位程序员可能都同意指针的大小等于各自机器的字长,但这个假设对于可移植的C/C++代码来说也是错误的!

第三位程序员经历了安装Windows编译器的痛苦过程,并构建了一个64位命令行应用(公平地说,安装OSX的命令行工具更糟糕;安装大多数操作系统的编译器都很麻烦)。当他们运行该程序时,看到的是:

sizeof(int): 4
sizeof(long): 4
sizeof(long long): 8
sizeof(void*): 8

这是第三种情况(故事中的第三位程序员)。在这种情况下,只有 sizeof(long long) 等于 sizeof(void*)

数据模型

这些程序员看到的情况被称为数据模型。

第一位程序员在一台64位的x86-64 OSX机器上运行,使用的是LP64数据模型,其中long(L),long long(更大的long long),以及指针(P)是64位的,但int是32位的。

第二位程序员在32位的x86 OSX机器上运行,使用的是ILP32数据模型,其中int(I),long(L),和指针(P)是32位的,但long long是64位的。

第三位程序员在64位的x86-64 Windows机器上运行,使用的是LLP64数据模型,其中只有long long(LL)和指针(P)是64位的,int和long是32位的。

数据模型sizeof(int)sizeof(long)sizeof(long long)sizeof(void*)示例
ILP3232b32b64b32bWin32, i386 OSX & Linux
LP6432b64b64b64bx86-64 OSX & Linux
LLP6432b32b64b64bWin64

还有一些更旧的数据模型,比如LP32(Windows 3.1,Macintosh,其中int是16位),以及一些更奇特的数据模型,如ILP64和SILP64。因此,了解数据模型对于编写可移植的C/C++代码非常重要。

历史背景

计算机中,地址空间不足的问题一直存在,并且会继续存在。随着计算机性能和内存的便宜,应用程序变得越来越大。公司希望销售具有更大字长的芯片来访问更多内存,但早期的采用者不想购买无法运行其最喜爱应用程序的计算机(因为应用程序还没有为新硬件编译)。有人大喊虚拟机,接着一个椅子飞过来。

本文强调了为什么LP64优于ILP64的原因:ILP64使得只需要32位精度的可移植C代码更难维护(在ILP64中,int是64位,而short是16位!)。它提到,如果数据结构不包含指针,它们的大小在LLP64和ILP32之间是相同的,这是微软的方向。LLP64本质上是具有64位指针的ILP32模型。

Linux还支持一个叫做x32的ABI,它可以使用x86-64 ISA的改进,但使用32位指针来减小数据结构的大小,避免使用64位指针。

如果想了解更多关于字长和数据模型的演变,以及由此产生的“苦难”,这篇论文是一个很好的参考。它描述了微软最终放弃对16位数据模型的支持,改为支持Windows XP 64位。它提到,业界在LP64、LLP64和ILP64之间分歧较大,因为从ILP32向移植的代码会以不同的方式出错。它还指出,Windows应用程序中使用long的情况更多,而Unix应用程序中使用int的情况更多。它还提出了一个关键点,很多来自ILP32时代的程序员假设 sizeof(int) == sizeof(long) == sizeof(void*),但在LP64/LLP64时代这并不成立。

论文还指出,C语言中的typedef直到1977年才加入,那时硬件制造商仍然无法达成一致,无法确定char(CHAR_BITS)有多少位,而有些机器使用的是24位寻址方案。stdint.h和inttypes.h还没有出现。

这篇文章讨论了从ILP32到LP64切换的两个主要类别的影响,并提供了非常好的代码示例。文章最后的那一节值得一读,提供了代码审查时要关注的要点。

结论

字长或ISA并不能告诉你 sizeof(int)、sizeof(long) 或 sizeof(long long) 的具体大小。我们还看到,一台机器可以支持多种不同的数据模型(当我用 -m32 标志编译并运行相同的代码时)。

C标准告诉你这些类型的最小保证大小,但数据模型(作为ABI的一部分,虽然外部但遵循C标准)则告诉你标准整数和指针的具体大小。

原文地址:Data Models and Word Size

补充内容

64-BIT PROGRAMMING MODELS

更多资料:

  • 64-Bit Programming Models: Why LP64?
  • The Long Road to 64 Bits
  • The UNIX System – 64bit and Data Size Neutrality
  • 64-bit data models
  • C Language Data Type Models: LP64 and ILP32
  • ILP64, LP64, LLP64
  • x32 ABI
  • difference between stdint.h and inttypes.h
  • Abstract Data Models
  • The New Data Types
  • Is there any reason not to use fixed width integer types (e.g. uint8_t)?
  • Why did the Win64 team choose the LLP64 model?
Post Views: 672
编程笔记

文章导航

Previous post
Next post

发表回复 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注

站内搜索

微信公众号

广告赞助

近期文章

  • 斯坦福 STORM 学习法:用 AI 深度研究一个主题,构建自己的知识体系
  • 如何使用 Claude 将任何知识的学习速度提升 10 倍【译】
  • Excel 根据数值正负自动设置文字颜色:正数红色、负数绿色
  • 2026 年主流跨端开发框架:Flutter、React Native、KMP 怎么选?
  • 2026 年企业级编程技术栈趋势简报
  • 使用 Jev 构建 Harness [译]
  • 2026年FDE(前沿部署工程师)为什么成了香饽饽?
  • 第 7 章 Tool System:给 AI 装上”手和脚”
  • 第 6 章 Context Engineering:Agent 的”工作内存”
  • 第 5 章 主流 AI Agent 架构模式

近期评论

  • 《AI Agent 架构设计与工程实践指南》——从 LLM、Agent、Harness 到 Mini Claude Code - 编程开物 发表在《第 3 章 AI Agent Loop:现代 AI Agent 背后的核心架构》
  • 《AI Agent 架构设计与工程实践指南》——从 LLM、Agent、Harness 到 Mini Claude Code - 编程开物 发表在《第 4 章 Agent Harness是什么?》
  • 第 4 章 Agent Harness是什么? - 编程开物 发表在《《AI Agent 架构设计与工程实践指南》——从 LLM、Agent、Harness 到 Mini Claude Code》
  • 《AI Agent 架构设计与工程实践指南》——从 LLM、Agent、Harness 到 Mini Claude Code - 编程开物 发表在《第 2 章 LLM Application 的基本架构》
  • 《AI Agent 架构设计与工程实践指南》——从 LLM、Agent、Harness 到 Mini Claude Code - 编程开物 发表在《第 1 章 重新认识 AI Agent》

归档

  • 2026 年 10 月 (2)
  • 2026 年 9 月 (14)
  • 2025 年 8 月 (1)
  • 2025 年 7 月 (1)
  • 2025 年 6 月 (10)
  • 2025 年 5 月 (10)
  • 2025 年 4 月 (5)
  • 2025 年 2 月 (1)
  • 2024 年 12 月 (4)
  • 2024 年 11 月 (7)
  • 2024 年 9 月 (1)
  • 2024 年 8 月 (4)
  • 2024 年 7 月 (1)
  • 2024 年 2 月 (1)
  • 2023 年 12 月 (3)
  • 2023 年 11 月 (6)
  • 2023 年 10 月 (4)
  • 2023 年 9 月 (2)
  • 2023 年 8 月 (38)
  • 2022 年 2 月 (1)
  • 2022 年 1 月 (13)
  • 2021 年 1 月 (1)
  • 2020 年 10 月 (1)
  • 2020 年 1 月 (1)
  • 2014 年 7 月 (2)

分类

  • IT项目管理 (2)
  • 实用技巧 (3)
  • 技术教程 (8)
  • 数据与AI (12)
    • AI基础理论 (1)
    • AI实践应用 (2)
    • 数据工程 (3)
  • 架构设计 (13)
    • AI应用架构设计 (8)
    • 传统应用架构设计 (2)
  • 编程基础 (2)
  • 编程笔记 (88)
  • 行业动态 (19)
©2026 编程开物 | WordPress Theme by SuperbThemes | 沪ICP备17019044号-3