• 大家觉得C/C++ 的 int、long 等不定宽类型是失败的设计吗?
  • 发布于 1个月前
  • 245 热度
    10 评论
如题,大家觉得C/C++ 的 int、long 等不定宽类型是失败的设计吗?,今天给 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 )
用户评论
  • 我怕黑
  • 还是因为历史的局限性吧? 当时的计算机处理器规格都各做各的, 兼容机都算是个不小的突破, 但是各家的位宽都不一样, 很多兼容软件的传递方式是以源码形式传递的, 就是为了方便用户编译到自己的机器上
  • 2025/3/9 15:49:00 [ 0 ] [ 0 ] 回复
  • 顾及谁
  • 这个问题的本质是 C/C++定位是系统编程语言,数字类型的是为了方便在不同指令集之间移植来设计的,比如说:
    * 所有类型都只有最小宽度而没有绝对宽度,因为不是所有指令集都有操作各种宽度的指令
    * int 就是在那个平台寻址范围内做下标比较合适的长度
    * short 就是可能比 int 节省空间,但是至少有 16 位; long 就是至少有 32 位

    当然我也觉得理想是美好的,现实是骨感的,这些语言出现不久互联网就爆发了,有了跨机型交换数据的需求,导致这些依平台而变的类型不好用。理论上说交换格式可以和内存里的数据类型分离,比如内存里的 struct 用 int, long 等类型,交换时翻译到到固定长度的 char[](这样还解决了 endianness ),但显然没有几个人这么勤快。当然我觉得 long long 出现时,这个情况已经很明显了,应该直接定义 int64 而不是新增一个关键字。
  • 2025/3/9 15:46:00 [ 0 ] [ 0 ] 回复
  • Zappos
  • 要甩锅那得甩给早期计算机的制造公司,尤其是 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 打补丁。

  • 2025/3/9 15:42:00 [ 0 ] [ 0 ] 回复
  • Cactus
  • 说白了 int long 不定宽是就刻意设计的,目的就是为了适应多样化的硬件,方便移植,保持最佳性能。
    posix 和 libc 也是从那个时代过来的,一直需要维持 API 兼容,所以这才是历史问题。
  • 2025/3/9 15:41:00 [ 0 ] [ 0 ] 回复
  • Pigeon
  • 目前正在开发跨平台应用,不等宽确实是一个不方便的设计。但是这些在设计过程中都可以规避,现在的 C++标准支持 int32_t 类似的 Fixed width integer types 定义。如果在实践过程中实在需要根据平台来使用不同长度的类型,一般是先定义一个类型,然后再使用不同平台的宏来定义不同长度。
  • 2025/3/9 15:39:00 [ 0 ] [ 0 ] 回复
  • APAC
  • 很大部分是历史原因,各种类型设备的出现,都需要 C/C++ 编写能运行在之上的程序(比如驱动),C++11 标准化的 (Fixed width integer types)[https://en.cppreference.com/w/cpp/types/integer] 就是为了方便编写可移植性代码,以前的都是完全由开发者用宏来处理数据类型的差异。
  • 2025/3/9 15:36:00 [ 0 ] [ 0 ] 回复
  • 李明发
  • 编程语言是服务于程序,而不是服务于程序员的,C/C++的很多设计都是出于性能考虑,数据类型也是一样的,C/C++都是 70 年代产生的语言,当时内存可能都不到 1M ,现在内存虽然大了,但是 CPU 缓存可能也就十几 M ,更别说还有嵌入式设备,而有些需求对于性能的追求是没上限的,很多 C 库,底层实际上是 SIMD 和汇编。
  • 2025/3/9 10:50:00 [ 0 ] [ 0 ] 回复
  • 山川皆无恙
  • 当然是失败设计。rust 的更好点。i8,i16,i32,i64 非常清楚。c 的 int 都在不同平台叫同一个名字。然而内存占用不一样。非常坑。

  • 2025/3/9 10:45:00 [ 0 ] [ 0 ] 回复