【问题标题】:What does 'Natural Size' really mean in C++?C++ 中“自然大小”的真正含义是什么?
【发布时间】:2014-06-23 16:22:49
【问题描述】:

我了解“自然大小”是由特定硬件最有效地处理的整数宽度。在数组或算术运算中使用short 时,必须首先将short 整数转换为int

问:究竟是什么决定了这种“自然尺寸”?

我不是在寻找简单的答案,例如

如果它有 32 位架构,它的自然大小是 32 位

我想了解为什么这是最有效的,为什么必须转换short在对其进行算术运算之前。

额外问题:当对long 整数进行算术运算时会发生什么?

【问题讨论】:

  • 谢谢大家的回答,我接受了 Sneftel 的回答,因为它对我帮助最大。

标签: c++ performance int long-integer short


【解决方案1】:

一般而言,每种计算机体系结构的设计都是为了使某些类型大小提供最有效的数值运算。具体大小取决于架构,编译器会选择合适的大小。关于为什么硬件设计人员为特定硬件选择特定尺寸的更详细解释将超出 stckoverflow 的范围。

在执行积分运算之前,short 大部分被提升为 int,因为它在 C 中就是这样,而 C++ 继承了这种行为,几乎没有理由改变它,可能会破坏现有代码。我不确定它最初是在 C 中添加的原因,但可以推测它与“默认 int”有关,如果没有指定类型 int 则由编译器假定。

奖励 A:从 5/9(表达式)我们学习:Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:

然后特别感兴趣:

  • 在这里无关紧要的浮点规则
  • Otherwise, the integral promotions (4.5) shall be performed on both operands
  • Then, if either operand is unsigned long the other shall be converted to unsigned long.
  • Otherwise, if one operand is a long int and the other unsigned int, then if a long int can represent all the values of an unsigned int, the unsigned int shall be converted to a long int; otherwise both operands shall be converted to unsigned long int.
  • Otherwise, if either operand is long, the other shall be converted to long.

总而言之,编译器尝试使用它可以执行二进制操作的“最佳”类型,int 是使用的最小大小。

【讨论】:

  • “总而言之,编译器尝试使用它可以执行二进制操作的“最佳”类型,其中 int 是使用的最小大小。 ~非常清楚,谢谢!
  • 此外,由于房地产或成本原因,某些处理器可能会限制自然词的大小。例如,一个 16 位的 CPU,它的数据总线需要 16 条线来传递数据。 32 位 cpu 需要双倍的空间来传递数据。请记住,这包括连接到算术逻辑单元 (ALU)、比较器、桶形移位器、乘法器和其他单元的线路,以及连接到外部设备(包括内存)的引脚。
  • 对大于处理器字长的数据类型执行操作时,处理器必须增加操作次数。例如,在 32 位机器上添加 64 位单元时,必须添加低位字,然后将任何进位提升到添加高位字。就像您在添加小数列(数字)时执行进位一样。
  • OP 提出了一个后续问题,我在我的 answer 中介绍了 C99 中这个问题的来源,并 +1 以获得很好的答案。
【解决方案2】:

“自然大小”是由特定硬件最有效地处理的整数宽度。

不是真的。考虑 x64 架构。从 8 位到 64 位的任何大小的算术运算速度基本相同。那么为什么所有 x64 编译器都选择 32 位 int 呢?好吧,因为那里有很多最初是为 32 位处理器编写的代码,其中很多隐含地依赖于 32 位的整数。并且考虑到可以表示高达 9 quintillion 的值的类型几乎无用,因此每个整数额外的四个字节实际上是未使用的。所以我们决定 32 位整数对于这个 64 位平台来说是“自然的”。

比较 80286 架构。寄存器中只有 16 位。在这样的平台上执行 32 位整数加法基本上需要将其拆分为两个 16 位加法。用它做几乎任何事情都涉及拆分它,真的——以及随之而来的减速。 80286 的“自然整数大小”绝对不是 32 位。

真的,“自然”归结为处理效率、内存使用和程序员友好性等考虑因素。这不是一个酸性测试。这很大程度上取决于架构/编译器设计者的主观判断。

【讨论】:

  • 这是我从这个答案中得到的,如果我解释错了,请纠正我。 64 位处理器将以相同的效率处理 8 位到 64 位之间的int 类型。通过扩展,32 位处理器将以相同的效率处理 8 到 32 位之间的int 类型。但是在 32 位处理器上使用 64 位 int 需要将其分成两个进程,这会影响效率,因此 64 位 int 不会是 32 位处理器的“自然大小”位处理器。这个“自然大小”是由编译器根据各种因素“选择”的。
  • 基本上,是的。值得注意的是, 一些处理器处理较小类型的速度较慢,尤其是在将它们传入和传出内存时。 PowerPC 就是一个很好的例子。
  • @dayuloli 实际上 int 根据标准必须至少为 16 位。
  • @larsmans 确实如此,但关于缩小带符号类型的(缺乏)规则基本上允许int8 = int8 + int16 完全通过 8 位操作发生,而不管涉及的假定类型提升。
  • 在 64 位系统上不将 int 设为 64 位的一个主要原因是它只会留下两种标准整数类型(charshort)来涵盖三种不同的大小(8 、16 和 32 位)。要使 ILP64 模型工作,您需要一个附加类型 (short short?),但 LP64 和 LLP64 与现有语言定义兼容。 unix.org/version2/whatsnew/lp64_wp.html 对此进行了详细讨论。
【解决方案3】:

究竟是什么决定了这个“自然大小”?

对于某些处理器(例如 32 位 ARM 和大多数 DSP 风格的处理器),它由架构决定;处理器寄存器是特定大小的,只能对那个大小的值进行算术运算。

其他的(例如 Intel x64)更灵活,没有单一的“自然”大小;由编译器设计者选择大小、效率、值范围和内存使用之间的折衷。

为什么这是最有效的

如果处理器要求值具有特定的算术大小,那么选择其他大小将迫使您将值转换为所需的大小 - 可能需要付出代价。

为什么在对它进行算术运算之前必须转换一个short

据推测,这与半个世纪前开发 C 语言时常用处理器的行为非常匹配。 C++ 继承了 C 的提升规则。我无法真正评论为什么它被认为是一个好主意,因为那时我还没有出生。

当对long 整数进行算术运算时会发生什么?

如果处理器寄存器足够大以容纳long,那么算法将与int 大致相同。否则,这些操作将不得不分解为对多个寄存器之间的值拆分的多个操作。

【讨论】:

  • 提升规则确保如果机器的寄存器是 32 位的并且指令对整个寄存器进行操作,则编译器不需要截断操作结果以返回 short (这可能需要额外的指令)。
  • 是什么决定了这个“自然大小”是由架构决定还是由编译器决定? (并且仅由架构或编译器决定?)通常由两者决定吗?从其他答案中,我得到的印象是编译器设计者可以在一个范围内进行选择。
  • 如果编译器设计者希望他的编译器的可执行文件能够与现有的系统库一起正常工作,他会自担风险。架构和操作系统确实是决定性因素。
  • @dayuloli:正如我所说:某些处理器仅支持特定数据大小的算术运算,因此这是“自然”大小的唯一明智选择。其他更灵活,允许对各种不同的数据大小进行算术运算,因此可以选择合适的大小。
【解决方案4】:

我了解“自然大小”是由特定硬件最有效地处理的整数宽度。

这是一个很好的开始。

问:究竟是什么决定了这种“自然大小”?

上面的段落是“自然大小”的定义。没有其他因素决定它。

我想了解为什么这是最有效的

根据定义。

以及为什么在对其进行算术运算之前必须转换一个short。

之所以如此,是因为 C 语言定义是这样说的。没有深层的架构原因(C 被发明时可能有一些原因)。

额外问题:当对长整数进行算术运算时会发生什么?

一束电子冲过肮脏的沙子,遇到一堆空洞。 (不,真的。问一个模糊的问题......)

【讨论】:

    猜你喜欢
    • 2012-05-18
    • 2013-06-28
    • 2013-02-02
    • 2017-05-06
    • 2012-03-30
    • 2011-10-10
    • 2012-08-03
    • 2012-01-30
    • 1970-01-01
    相关资源
    最近更新 更多