【问题标题】:Size of Primitive data types原始数据类型的大小
【发布时间】:2010-12-30 11:34:55
【问题描述】:

int 这样的原始数据类型的大小究竟取决于什么?

  • 编译器
  • 处理器
  • 开发环境

或者是这些或其他因素的组合?
解释相同的原因将非常有帮助。

编辑:很抱歉造成混淆..我的意思是询问像 int 这样的原始数据类型,而不是关于 POD,我确实理解 POD 可以包含结构,并且结构是一个完全不同的球赛,其中填充进入图片. 我已经更正了 Q,这里的编辑说明应该确保关于 POD 的答案看起来不相关。

【问题讨论】:

  • 您是指原始(或内置)类型,还是实际的POD类型(结构、联合)?
  • @Alex, @Als:一个重要的问题。
  • C++ : size of int, long, etc... 的可能重复项

标签: c++ c sizeof


【解决方案1】:

我认为这个问题有两个部分:

  1. 允许原始类型的大小。
    is specified by the C and C++ standards:类型已允许它们必须具有的最小值范围,这隐含地为其大小设置了一个下限以位为单位(例如,long 必须至少为 32 位以符合标准)。
    标准没有以字节为单位指定大小,因为 definition of the byte 取决于实现,例如char 是字节,但字节大小(CHAR_BIT 宏)可能是 16 位。

  2. 实现定义的实际大小。
    正如其他答案已经指出的那样,这取决于实现:编译器。反过来,编译器的实现也受到目标架构的严重影响。因此,让两个编译器在相同的操作系统和架构上运行但具有不同大小的int 是合理的。您可以做出的唯一假设是标准规定的假设(假设编译器实现了它)。
    还可能有额外的 ABI 要求(例如固定大小的枚举)。

【讨论】:

  • 应该注意的是,主要系统的绝大多数实现都试图遵守现有的 ABI 规范,该规范指定大多数或所有类型的大小和格式,以促进不同工具或不同工具之间的兼容性同一工具的版本。
  • @Thomas : char 的大小由 Standard 自己定义,为 1。请看我的帖子。
  • @Nawaz,sizeof char 始终为 1,但 CHAR_BIT 可能 >= 8,因此 char 的实际大小(以位为单位)将大于 8。
  • @Nawaz,不,C 标准不需要它,它只暗示它应该至少为 8(因为允许的 char 值范围)。只有 POSIX 要求它是 8 位的。以下是 C99 标准评论文档的摘录:“C 并未与 8 位字节结合,尽管该值隐含在其中写入的大部分源代码中。[...] 一些 DSP 芯片具有 16 位或32 位字符类型(这与可寻址性问题有关,而不是字符集大小)。”
  • @Nawaz 这个来自评论。在实际标准中,它在第 5.2.4.2.1(1) 节中:“下面给出的值应替换为适用于 #if 预处理指令的常量表达式。[...] 它们的实现定义值应等于或量级(绝对值)大于所示的值,符号相同。”也在附录 E:实施限制中。
【解决方案2】:

首先,它依赖于编译器。编译器通常取决于架构、处理器、开发环境等,因为它会将它们考虑在内。所以你可以说它是所有的组合。 但我不会这么说。我想说,编译器,因为在同一台机器上,如果您使用不同的编译器,您可能有不同大小的 POD 和 内置 类型。另请注意,您的源代码是编译器的输入,因此编译器会最终决定 POD 的大小和内置类型。然而,这个决定也确实受到目标机器的底层架构的影响。毕竟,真正的有用编译器必须发出高效最终在您的目标机器上运行的代码。

编译器也提供options。其中很少有人会影响尺寸!


编辑:标准怎么说,


charsigned charunsigned char 的大小由 C++ 标准本身定义!所有其他类型的大小由编译器定义。

C++03 标准 $5.3.3/1 说,

sizeof(char), sizeof(signed char) 和 sizeof(unsigned char) 为 1;这 sizeof 应用于任何其他的结果 基本类型(3.9.1)是 实现定义。 [注:在 特别是 sizeof(bool) 和 sizeof(wchar_t) 是 实现定义.69)

C99 Standard ($6.5.3.4) 本身也将 charsigned charunsigned char 的大小定义为 1,但其他类型的大小由编译器定义!


编辑:

我发现这个 C++ FAQ 章节非常好。整章。虽然是很小的一章。 :-)

http://www.parashift.com/c++-faq-lite/intrinsic-types.html


还请阅读下面的 cmets,有一些很好的论据!

【讨论】:

  • 严格来说,它只取决于编译器。 CPU 只会影响哪种布局会更有效,但编译器原则上可以做任何它喜欢的事情。它不必考虑 CPU 的对齐要求、寄存器大小或其他任何东西,只要它生成的代码可以工作。
  • @jalf:虽然有些架构在数据对齐方面确实很无情(例如 IA64)。
  • @In silico: 这只是意味着编译器必须生成额外的代码来处理它。 (它可以进行两次对齐加载,然后将结果合并到寄存器中。当然,这很昂贵,但它允许编译器即使在不直接支持它的 CPU 上也可以进行非对齐加载)
  • @jalf :由于编译器是建立在底层架构上的,所以你不能说它不会影响它的选择!这只是一个表达的问题,如果你说它只取决于编译器,那它只意味着如果编译器想要那么它可以实现 sizeof(int) = 128。但它没有,因为它尊重架构!事实上,如果它想发出高效的代码,就必须尊重架构!
  • @jalf :我确定话题发起者不想知道现实世界中不存在的东西。我要说的是,在现实的编程世界中,底层架构确实会影响编译器的选择,就像您的银行余额会影响您在超市购买的东西的选择一样。 :-)
【解决方案3】:

如果您询问像int 这样的原始 类型的大小,我会说这取决于您引用的因素。

编译器/环境对(其中环境通常表示操作系统)肯定是其中的一部分,因为编译器可以出于各种原因以不同方式将各种“合理”大小映射到内置类型上:例如,x86_64 上的编译器Windows 通常会有一个 32 位 long 和一个 64 位 long long 以避免破坏纯 x86 的代码;而在 x86_64 Linux 上,long 通常是 64 位的,因为它是一个更“自然”的选择,并且为 Linux 开发的应用程序通常更独立于架构(因为 Linux 运行在更多种类的架构上)。

处理器在决定中肯定很重要:int 应该是处理器的“自然大小”,通常是处理器通用寄存器的大小。这意味着它是在当前架构上运行速度更快的类型。 long 通常被认为是一种以性能换取扩展范围的类型(这在普通 PC 上很少发生,但在微控制器上是正常的)。

如果你也在谈论structs & co。 (如果它们遵守某些规则,POD),编译器和处理器也会影响它们的大小,因为它们是由内置类型和编译器选择的适当填充来实现的目标架构上的最佳性能。

【讨论】:

    【解决方案4】:

    正如我在@Nawaz 的回答下评论的那样,它在技术上完全取决于编译器。

    编译器的任务只是获取有效的 C++ 代码,并输出有效的机器代码(或它所针对的任何语言)。

    因此,C++ 编译器可以决定使 int 的大小为 15,并要求它在 5 字节边界上对齐,它可以决定在 POD 中的变量之间插入任意填充。标准中没有任何内容禁止这样做,它仍然可以生成工作代码。

    它会慢得多。

    因此,在实践中,编译器通过两种方式从它们运行的​​系统中获取一些提示: - CPU 有一定的偏好:例如,它可能有 32 位宽的寄存器,所以将 int 设为 32 位宽是个好主意,而且它通常要求变量自然对齐(一个 4 字节宽的变量例如,必须在可被 4 整除的地址上对齐),因此 sensible 编译器会尊重这些偏好,因为它会产生更快的代码。 - 操作系统也可能有一些影响,因为如果它使用除编译器之外的其他 ABI,则进行系统调用将变得不必要地困难。

    但这些只是让程序员的生活更轻松或生成更快代码的实际考虑。它们不是必需的

    编译器拥有最终决定权,它可以选择完全忽略 CPU 和操作系统。只要它生成具有 C++ 标准中指定语义的工作可执行文件。

    【讨论】:

    • 编译器必须定义类型的大小以满足标准中指定的范围。对于 8 位(八位字节)平台,编译器至少需要两个八位字节才能满足整数的范围规范。
    • 当然。这就是我在上一段中所说的。它必须生成一个遵循 C++ 语义的可执行文件(其中,指定某些数据类型的最小大小)
    【解决方案5】:

    这取决于实现(编译器)。

    Implementation-defined behavior 表示未指定的行为,其中每个实现都记录了如何做出选择。

    【讨论】:

    • FWIW,编译器必须分配足够的位来分配 C 语言标准(规范)中指定的范围。如果编译器想对整数使用 1024 位,它可以并且仍然符合标准。
    【解决方案6】:

    struct 也可以是 POD,在这种情况下,您可以在某些编译器上使用 #pragma pack 显式控制成员之间的潜在填充。

    【讨论】:

      猜你喜欢
      • 2018-03-17
      • 2014-04-26
      • 2021-05-10
      • 1970-01-01
      • 2016-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-06
      相关资源
      最近更新 更多