除了char之外,为什么sizeof内置类型在C&C ++中依赖于编译器?

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

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

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

此外,在计算的早期阶段,浮点格式和大小通常远不那么标准化(IEEE 754直到1985年才出现),这就是为什么float s和double s甚至比整数数据更不明确的原因类型。 他们通常甚至不假设存在诸如无穷大,NaN或有符号零的特殊性。

此外,或许应该说char不是定义为1个字节,而是为了返回1的sizeof 。 这不一定是8位。 (为了完整起见,也许应该在这里添加,作为术语的“ 字节 ”不是普遍定义为8位;它有许多历史定义,并且在ANSI C标准的上下文中,“ byte“实际上被定义为可以存储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的实现是否是C类似于争论Scots是否是英语,因为它几乎没有意义。 他们使用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时,他们想到的一个重要目标是网页applet。 它们专门用于限制Java,使最终用户可以运行任何Java小程序,并且知道它不可能损害他们的机器。

当然,情况已经发生了变化 – 他们所针对的安全性仍然是难以捉摸的,并且applet基本上已经死了而且已经消失了。 尽管如此,旨在支持该模型的大多数限制仍然存在。

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

当然,这也不是完成大致相同的事情的唯一可能方式。 例如,阿达采取了一种不同的路线。 而不是“本机”类型面向机器,然后添加具有保证属性的特殊类型,它走向另一个方向,并且具有保证属性的本机类型,而且还有用于定义直接对应的新类型的整个工具。目标机器。 然而,无论好坏,Ada从未达到过与C,C ++或Java一样广泛的用途,并且它对这个特定问题的处理方式似乎也没有被许多其他语言采用。