为什么 sizeof 内置类型(char 除外)在 C 和 C++ 中依赖于编译器?

Why sizeof built in types except char is compiler dependent in C & C++?

本文关键字:C++ 依赖于 编译器 内置 sizeof 置类型 除外 char 为什么      更新时间:2023-10-16

为什么 C 和 C++ 中的基本类型没有严格定义,就像在 Java 中那样,int总是 4 个字节,long 是 8 个字节,等等。据我所知,在 C 和 C++ 中,只有一个char被定义为 1 字节,其他所有内容都由不同的编译器定义不同。因此,C 和 C++ 中的int不一定是 4 个字节,只要它比 short 长,short char长。
我只是想知道为什么会这样,它有什么用吗?

原因主要是因为 C 可以移植到更广泛的平台上。不同的数据类型在各种平台上变成不同的大小有很多原因,但至少从历史上看,int已被改编为平台的原生字大小。在PDP-11上,它是16位(long最初是为32位数字发明的),而一些嵌入式平台编译器甚至具有8位int。当 32 位平台出现并开始具有 32 位 int 时,发明了 short 来表示 16 位数字。

如今,大多数 64 位架构使用 32 位 int 只是为了与最初为 32 位平台编写的大量 C 程序兼容,但也有具有 64 位 int 的 64 位 C 编译器,尤其是一些早期的 Cray 平台。

此外,在计算的早期,浮点格式和大小通常不太标准化(IEEE 754 直到 1985 年才出现),这就是为什么 float s 和 double s 的定义甚至不如整数数据类型。他们通常甚至不假设存在无穷大、NaN 或有符号零等特性。

此外,也许应该说,char不是定义为 1 个字节,而是定义为sizeof返回 1 的任何字节。这不一定是 8 位。(为了完整起见,也许应该在这里补充一点,"字节"作为一个术语并没有被普遍定义为8位;它有很多历史定义,在ANSI C标准的背景下,"字节"实际上被定义为可以存储char的最小存储单位, 无论char的性质如何。

还有诸如 36 位 PDP-10 和 18 位 PDP-7 之类的体系结构也运行 C 程序。如今,它们可能非常罕见,但确实有助于解释为什么 C 数据类型不是根据 8 位单位定义的。

这最终是否真的使该语言比Java等语言"更具可移植性",也许可以争论,但是在16位处理器上运行Java程序肯定是次优的,而且在36位处理器上运行确实很奇怪。也许可以公平地说,它使语言更具可移植性,但用它编写的程序的可移植性降低。

编辑:在回复一些评论时,我只想附上,作为一个观点,C作为一种语言不同于Java/Haskell/ADA等语言,这些语言或多或少是由公司或标准机构"拥有"的。当然有ANSI C,但C比ANSI C更多;这是一个活生生的社区,有许多实现与ANSI不兼容,但仍然是"C"。争论使用 8 位 int s 的实现是否是 C 类似于争论苏格兰语是否是英语,因为它基本上毫无意义。他们使用 8 位ints是有充分理由的,任何了解 C 语言的人都无法推理为此类编译器编写的程序,任何为此类架构编写 C 程序的人都希望他们的int为 8 位。

没有严格指定整型数据类型,以便编译器可以为目标硬件选择最有效的数据类型。 但是,每种类型的最小尺寸都有一些保证(例如 int至少为 16 位)。

查看此页面: http://en.cppreference.com/w/cpp/language/types

效率是答案的一部分 - 例如,如果您在使用 36 位寄存器的计算机上使用 C 或 C++,则不希望强制每个操作都包含开销来掩盖结果,以便它们看起来/行为像 32 位。

不过,这实际上只是答案的一部分。另一部分是C和C++曾经(现在)打算成为系统编程语言。你打算能够用它们编写虚拟机和操作系统等内容。

这意味着,如果(例如)您正在编写将在此 36 位计算机上与 MMU 交互的代码,并且您需要设置某个特定单词的第 34 位,则 C 和 C++ 的基本意图是您应该能够直接在语言中执行此操作。如果语言一开始就规定不能存在 36 位类型,这通常使得在该语言中直接操作 36 位类型变得困难。

因此,C 和 C++ 的基本前提之一是,如果你需要做某事,你应该能够在语言做某事。Java中的相应前提几乎完全相反:它允许你做的事情应该仅限于那些它可以保证安全且可移植到任何东西的操作。

特别是,请记住,当Sun设计Java时,他们想到的一个大目标是网页的小程序。他们特别打算将Java限制到最终用户可以运行任何Java小程序的程度,并且知道它不会损害他们的机器,从而感到安全。

当然,情况已经发生了变化——他们所追求的安全仍然难以捉摸,小程序基本上已经死了。尽管如此,旨在支持该模式的大多数限制仍然存在。

我可能应该补充一点,这并不完全是一种非此即彼的情况。有许多方法可以提供一些中间立场。C 和 C++ 标准的合理最新迭代包括int32_t的类型。这保证了 32 位 2 的补码表示,就像 Java 类型一样。因此,如果您在实际支持 32 位二进制补码类型的硬件上运行,则int32_t将存在,您可以使用它。

当然,这也不是完成大致相同事情的唯一可能方法。例如,Ada采取了一条略有不同的路线。它不是将"本机"类型面向计算机,然后添加具有保证属性的特殊类型,而是相反的方向,并且具有具有保证属性的本机类型,而且还具有用于定义直接对应于目标计算机的新类型的整个工具。然而,无论好坏,Ada 从未像 C、C++ 或 Java 那样获得如此广泛的使用,而且它解决这个特定问题的方法似乎也没有被许多其他语言采用。