V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
w568w
V2EX  ›  程序员

现在来看, C/C++ 的 int、long 等不定宽类型是失败的设计吗?

  •  
  •   w568w · 23 小时 24 分钟前 · 1804 次点击
    如题,今天给 C 库写其他语言 binding 的时候想到的。

    论据 1:C/C++ 之后,几乎所有语言都 (1) 定死了各个整数类型的宽度(如 Java ),或者 (2) 换用定宽类型(例如 i64 、u32 、int64 、usize )。即使 C 自己也引入了 int64_t 这样的固定宽度类型。

    论据 2:非常不利于编写可移植的库。比如用两个不同编译器编译出的代码,虽然函数声明一样,但因为一边 long 是 64 位整数,另一边是 32 位整数,导致不能互相调用。

    论据 3:不确定宽度导致程序员不得不随时检查数值范围,一旦疏忽(例如,换了新平台或者编译器)很容易造成溢出问题。为了检查,编写大量含宏代码,给程序员带来额外心智负担。

    论据 4:使数值类型系统变得过于复杂,很多场景下并不需要严格区分 long long 、long 、int 、short 、char 。但程序员由于认识不清楚而随意使用,反而可能造成 linter 不能正确给出 warning 。

    ---

    这个 int 、long 不定宽的规定是当时随意决定的吗?还是刻意设计出来的?为什么直到今天还有大量 C 库、接口仍在使用这样的类型?(例如 POSIX 、libc 、OpenMP )
    27 条回复    2025-03-09 20:16:41 +08:00
    ebi5oowiiy1llo
        1
    ebi5oowiiy1llo  
       23 小时 12 分钟前 via Android   ❤️ 1
    刻意设计出来的,为了匹配当时的处理器的一个 world ,参考: https://www.quora.com/Why-are-type-sizes-inconsistent-among-different-platforms-eg-short-int-long-in-C
    Nasei
        2
    Nasei  
       23 小时 12 分钟前
    如果让我从 c99 前的整数类型和 java 的整数类型二选一,我还是选宁愿用 c 的
    buxudashi
        3
    buxudashi  
       23 小时 12 分钟前   ❤️ 1
    当然是失败设计。

    rust 的更好点。i8,i16,i32,i64 非常清楚。c 的 int 都在不同平台叫同一个名字。然而内存占用不一样。非常坑。
    coderluan
        4
    coderluan  
       22 小时 57 分钟前   ❤️ 3
    编程语言是服务于程序,而不是服务于程序员的,C/C++的很多设计都是出于性能考虑,数据类型也是一样的,C/C++都是 70 年代产生的语言,当时内存可能都不到 1M ,现在内存虽然大了,但是 CPU 缓存可能也就十几 M ,更别说还有嵌入式设备,而有些需求对于性能的追求是没上限的,很多 C 库,底层实际上是 SIMD 和汇编。
    wnpllrzodiac
        5
    wnpllrzodiac  
       22 小时 52 分钟前   ❤️ 1
    时代的局限性,盖茨都说过 64k 已经够用了。
    vituralfuture
        6
    vituralfuture  
       22 小时 47 分钟前 via Android
    这样做是为了实现通过宏检测 feature 后,可以一份源码在不同平台使用不同编译器也能编译出正确的程序
    justou
        7
    justou  
       22 小时 42 分钟前
    很大部分是历史原因,各种类型设备的出现,都需要 C/C++ 编写能运行在之上的程序(比如驱动),C++11 标准化的 (Fixed width integer types)[https://en.cppreference.com/w/cpp/types/integer] 就是为了方便编写可移植性代码,以前的都是完全由开发者用宏来处理数据类型的差异。
    Thymolblue
        8
    Thymolblue  
       22 小时 30 分钟前
    目前正在开发跨平台应用,不等宽确实是一个不方便的设计。但是这些在设计过程中都可以规避,现在的 C++标准支持 int32_t 类似的 Fixed width integer types 定义。如果在实践过程中实在需要根据平台来使用不同长度的类型,一般是先定义一个类型,然后再使用不同平台的宏来定义不同长度。
    icyalala
        9
    icyalala  
       22 小时 9 分钟前
    早期硬件什么设计都有,int long 这些类型不定长反而才能可移植。你知道 char 有可能不是 8bit 吗?
    至于现在跨平台基本都在用 stdint.h 里面那些定义,C99 就支持了。
    moudy
        10
    moudy  
       22 小时 1 分钟前 via iPhone
    @vituralfuture 完全可以通过 feature 检测后用 typedef 来换数据类型。int 不等宽除了方便 compiler 实现,真没啥实际好处。
    icyalala
        11
    icyalala  
       22 小时 1 分钟前   ❤️ 1
    说白了 int long 不定宽是就刻意设计的,目的就是为了适应多样化的硬件,方便移植,保持最佳性能。
    posix 和 libc 也是从那个时代过来的,一直需要维持 API 兼容,所以这才是历史问题。
    cnbatch
        12
    cnbatch  
       22 小时 0 分钟前   ❤️ 6
    要甩锅那得甩给早期计算机的制造公司,尤其是 DEC

    UNIX 是在 PDP-7 开发出来的,而 PDP-7 的一个 Word (当时的最小操作单位)是 18 字节:
    https://gunkies.org/wiki/PDP-7

    在 C 语言诞生的那个年代,既有 PDP-11 ( C 语言初版诞生的平台),使用现在大家熟知的 16bit / 32bit / 64bit 操作方式;也有 PDP-12 ,使用的是 12-bit ,以现在的标准来看够奇怪吧。

    如果当时直接定死了各个基础类型的宽度,那么想要做源码级移植就麻烦多了。

    就像如此简单的代码:

    int number = 12;
    printf("Number: %d\n", number);

    int 是 18-bit 还是 12-bit ,又或者是 16-bit ,都由目标机器的编译器自己决定,在当时来看显然是很省事的。

    发明人哪能预料到后来会统一为 8 / 16 /32 / 64 bit 标准呢

    ---------------

    当然啦,ANSI / ISO 也有部份责任,第一个 ANSI C 标准制定的年代,已经是 8 / 16 /32 / 64 bit 标准的时期了,完全可以区分得更清晰一些,比如这样:

    int 必须比 short 宽,long 必须比 int 宽

    可惜标准只规定了最低限度,搞得后来不同系统的 int 和 long 都一塌糊涂。到了 C99 就只能用 macro 打补丁。
    cnbatch
        13
    cnbatch  
       21 小时 35 分钟前
    @cnbatch 勘误一下,DP-7 的一个 Word (当时的最小操作单位)是 18 比特(不是字节)

    补充一个:IBM 的“锅”也不小,DEC 之所以这么设计,可能是受到 IBM 的影响(毕竟要跟 IBM 竞争)。PDP-1 诞生前的 IBM 机器,字长就是 36-bit ,这里有发展史可以看:
    https://en.wikipedia.org/wiki/Word_(computer_architecture)

    1970 年之前的硬件操作数长度标准简直乱作一团
    cnbatch
        14
    cnbatch  
       21 小时 27 分钟前
    @moudy 早期 C 语言可没有 typedef 这种做法,有人提到这么一句——
    there is no "typedef" in early C
    出处: https://news.ycombinator.com/item?id=13441621
    billccn
        15
    billccn  
       21 小时 16 分钟前
    这个问题的本质是 C/C++定位是系统编程语言,数字类型的是为了方便在不同指令集之间移植来设计的,比如说:

    * 所有类型都只有最小宽度而没有绝对宽度,因为不是所有指令集都有操作各种宽度的指令
    * int 就是在那个平台寻址范围内做下标比较合适的长度
    * short 就是可能比 int 节省空间,但是至少有 16 位; long 就是至少有 32 位

    当然我也觉得理想是美好的,现实是骨感的,这些语言出现不久互联网就爆发了,有了跨机型交换数据的需求,导致这些依平台而变的类型不好用。

    理论上说交换格式可以和内存里的数据类型分离,比如内存里的 struct 用 int, long 等类型,交换时翻译到到固定长度的 char[](这样还解决了 endianness ),但显然没有几个人这么勤快。

    当然我觉得 long long 出现时,这个情况已经很明显了,应该直接定义 int64 而不是新增一个关键字。
    paopjian
        16
    paopjian  
       21 小时 15 分钟前
    还是因为历史的局限性吧? 当时的计算机处理器规格都各做各的, 兼容机都算是个不小的突破, 但是各家的位宽都不一样, 很多兼容软件的传递方式是以源码形式传递的, 就是为了方便用户编译到自己的机器上,
    billccn
        17
    billccn  
       20 小时 56 分钟前
    @cnbatch 我发出来才看见你的,我觉得你说的“int 必须比 short 宽,long 必须比 int 宽”虽然让部分初学者可以更清楚的了解这些类型的区别,但是与系统编程语言的定位不符合。比如说我记得早期的 64 位机就有完全不支持 16 位长度的指令集,这样 short 也必须是至少 32 位,那么 int 就得 64 位,long 不能 128 位吧?
    billccn
        18
    billccn  
       20 小时 48 分钟前
    @paopjian 这个问题到现在还有啊,比如嵌入式系统 32 位的已经很高级了,用 8 位机的也大有人在,很多机器连整数除法都做不了,这也是 C/C++最大的客户群。
    adian
        19
    adian  
       18 小时 52 分钟前
    这不是设计问题,是当时的硬件问题
    cnbatch
        20
    cnbatch  
       18 小时 10 分钟前
    @billccn 或许,特殊机器可以特殊对待,比如以编译器 extension 的形式去处理。
    假设“标准状况”下,char: 8-bit, short: 16-bit, int: 32-bit, long: 64-bit
    那么开启 extension 就无视标准规定,按照机器的硬件手册内容去做。

    如果硬件级别无法支持“假设的标准状况”,那就强制必须使用 extension 模式。

    当然啦,这都是马后炮了,我有这种想法(强制开启 extension )主要是因为知道 Linux 内核源码长期以来大量使用编译器扩展模式。微软编译自家系统时应该也是这样( MSVC 也有自己的 extension )。对于 20 世纪 80 年代的标准制定者而言,可能都预料不到编译器 extension 会用得满天飞。
    mayli
        21
    mayli  
       17 小时 49 分钟前
    当初差不多没有标准化的 8/16/32 , 当时的字长一大堆,有 9 12 啥的,你这论调属于事后诸葛亮,新语言基本上都是 64 位处理器起跳了
    iorilu
        22
    iorilu  
       13 小时 50 分钟前
    当时电脑, 能扣几个字节都干的
    tdxdxoz
        23
    tdxdxoz  
       8 小时 4 分钟前 via Android
    rust 的 usize 也是不定宽的啊,你为什么说“例如 i64 、u32 、int64 、usize ”
    ugpu
        24
    ugpu  
       1 小时 57 分钟前
    好比工地钻头,尺寸不一 你说他们不严谨?不照样摩天大楼如雨后春笋冒出来嘛?

    都是符合当时的业务背景需求罢了, 不是那么严谨的产业 只是基础服务设施 不行在升级迭代就行了. 至于内存?不够就加, 硬盘不够就扩容; 实在到了拿节骨眼上, 企业也会舍得花钱重建;
    至于一开始就一眼观望未来产生精妙的设计结构 的计算机语言 符合未来几十年的体系 业务。 只有两种可能:
    1. 运气好 营销也到位 存粹撞上了 该的。
    2. 造物主说的,就要这么干 我说的就是对的。
    普通人?忙着吃饭挣钱过好日子呢。造福全球人类的计划怕是一提出来 结合设计经费; 在资本家看来这是他们的命
    moudy
        25
    moudy  
       1 小时 46 分钟前
    @cnbatch #14 早期是早期,后面 C90 C99 还不在这个问题上做出更新就是不负责任。也直接导致了 64 位 c 编程时 int long longlong 实际宽度的混乱。
    moudy
        26
    moudy  
       1 小时 45 分钟前
    @billccn #17 指令集和数据宽度没直接关系哦。64 位指令也可以只操作 byte halfword
    moudy
        27
    moudy  
       1 小时 40 分钟前
    @ugpu #24 技术标准上定一个指标,不给指标上下界真的是不严谨。老罗在星巴克被中杯 大杯 超大杯都折磨成啥样了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2922 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 13:57 · PVG 21:57 · LAX 06:57 · JFK 09:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.