在C++中,“自然大小”真正意味着什么?

7

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

问:到底是什么决定了这个“自然大小”?

我不想要简单的答案,例如:

如果它有32位架构,则自然大小为32位

我想要明白为什么这是最有效的,以及为什么在对其进行算术运算之前必须将short转换。

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


谢谢大家的回答,我已经接受了Sneftel的答案,因为它对我帮助最大。 - dayuloli
4个回答

8
一般来说,每个计算机 架构都被设计成某种类型大小提供最有效的数字运算。具体的大小取决于架构,编译器将选择适当的大小。关于硬件设计师为特定硬件选择某些大小的更详细解释将超出stackoverflow 的范围。
在执行整数操作之前,必须将short提升为int,因为这是C语言中的方式,并且C++在没有或几乎没有理由改变它的情况下继承了这种行为,可能会破坏现有的代码。我不确定最初将其添加到C语言的原因,但可以推测它与“默认int”有关,即如果未指定类型,则编译器假定为int
奖励A:从5/9(表达式)中,我们了解到:许多二进制运算符期望算术或枚举类型的操作数,以类似的方式进行转换并生成结果类型。目的是产生一个公共类型,也是结果类型。这种模式称为通常的算术转换,其定义如下: 然后具体感兴趣:
- 浮点规则在此处无关紧要 - 否则,将对两个操作数执行整数晋升(4.5) - 然后,如果任一操作数为unsigned long,则另一个操作数应转换为unsigned long。 - 否则,如果一个操作数是long int而另一个操作数是unsigned int,则如果long int可以表示所有unsigned int的值,则将unsigned int转换为long int;否则,两个操作数都应转换为unsigned long int。 - 否则,如果任一操作数为long,则另一个操作数应转换为long。 总之,编译器尝试使用“最好”的类型来进行二进制运算,其中int是使用的最小大小。

总之,编译器尝试使用“最佳”类型来执行二进制操作,其中int是使用的最小大小。~非常清楚,谢谢! - dayuloli
此外,一些处理器可能会限制自然字的大小,原因是房地产或成本。例如,16位CPU需要16条数据总线来传递数据。32位CPU需要双倍的空间来传递数据。请记住,这包括到算术逻辑单元(ALU)、比较器、桶移位器、乘法器和其他单元的线路,以及连接到外部设备(包括内存)的引脚。 - Thomas Matthews
当对大于处理器字长的数据类型执行操作时,处理器必须增加操作次数。例如,在32位机器上添加64位单元时,必须先添加低位,然后将任何进位提升到高位的加法中。就像在添加十进制列(数字)时执行进位一样。 - Thomas Matthews
1
楼主提出了一个后续问题,我在我的答案中讲解了C99中这个问题的来源,并给你的不错的回答点赞。 - Shafik Yaghmour

7
“自然大小”是指特定硬件最有效处理的整数宽度。但并非总是如此,以x64架构为例,8到64位的任何大小的算术运算速度基本相同。那么为什么所有x64编译器都采用32位int呢?原因在于有很多代码最初是为32位处理器编写的,并且其中很多隐含地依赖于int为32位。鉴于一个类型可以表示高达9万亿的值几乎没有用处,每个整数额外的四个字节将几乎未被使用。所以我们决定,在这个64位平台上,32位int是“自然”的选择。与此相比,80286架构只有16位寄存器。在这样的平台上执行32位整数加法基本上需要将其分成两个16位加法。实际上,对它进行任何操作都需要分割它,从而导致速度变慢。80286的“自然整数大小”绝对不是32位。因此,“自然”实际上取决于处理效率、内存使用和程序员友好性等考虑因素。它不是一个酸性测试,而是架构/编译器设计者主观判断的问题。

以下是我从这个答案中得到的内容,请纠正我是否理解错误。64位处理器将以基本相同的效率处理8位到64位之间的“int”类型。同样,32位处理器将以相同的效率处理8位到32位之间的“int”类型。但在32位处理器上使用64位“int”需要将其分成两个进程,这将影响效率,因此,64位“int”不是32位处理器的“自然尺寸”。而这个“自然尺寸”是由编译器根据各种因素“选择”的。 - dayuloli
1
基本上是这样的。值得注意的是,在某些处理器上,处理较小的类型会更慢,特别是在将它们传输到和从内存中传输时。PowerPC就是一个很好的例子。 - Sneftel
1
实际上,“int”根据标准至少必须为16位。 - Fred Foo
@larsmans 这是真的,但是关于有符号类型缩小的规则(缺乏)基本上允许 int8 = int8 + int16 完全通过8位操作进行,而不管所涉及的推广类型。 - Sneftel
1
不将int设置为64位的主要原因是,在64位系统上只剩下两种标准整数类型(charshort)来覆盖三种不同的大小(8、16和32位)。为了使ILP64模型工作,您需要一个额外的类型(short short?),但LP64和LLP64与现有的语言定义兼容。这在http://www.unix.org/version2/whatsnew/lp64_wp.html中有详细讨论。 - dan04
不是真的。在x86_64中,64位除法仍然比8位除法慢得多,正如您可以在延迟列表中看到的那样。加法/减法的速度也是一样的。 - phuclv

3
“自然大小”是什么决定的?
对于一些处理器(例如32位ARM和大多数DSP风格的处理器),它由架构决定;处理器寄存器具有特定的大小,算术运算只能在该大小的值上进行。
其他处理器(例如Intel x64)更加灵活,没有单一的“自然”大小;这取决于编译器设计者选择一个尺寸,即在效率、值范围和内存使用之间做出妥协。
为什么这样最有效?
如果处理器要求算术值具有特定的大小,则选择另一个大小将强制您将值转换为所需的大小-可能会产生成本。
为什么在对短整型进行算术操作之前必须进行转换?
据推测,当C语言开发时,这与常用处理器的行为非常匹配,而那时已经过去了半个世纪。 C++从C继承了提升规则。我无法确切地评论为什么被认为是个好主意,因为那时我还没出生。
当对长整型进行算术操作时会发生什么?
如果处理器寄存器足够大以容纳长整型,则算术运算与int基本相同。否则,操作将被分解为对分裂在多个寄存器之间的值进行的多个操作。

晋升规则确保如果机器的寄存器为32位并且指令操作整个寄存器,则编译器无需截断操作结果以获取“short”(这可能需要额外的指令)。 - Fred Foo
这个“自然大小”是由架构还是编译器决定的?(它仅由架构或编译器决定吗?)通常是由两者共同决定的吗?从其他答案中,我得出的印象是编译器设计人员可以在一定范围内进行选择。 - dayuloli
一个编译器的设计者要自行决定是否愿意冒险,如果他想让编译器的可执行文件与现有系统库正常工作。架构和操作系统是真正的决定因素。 - Sneftel
正如我所说:有些处理器只支持特定数据大小的算术运算,因此这是唯一明智的选择。其他处理器更加灵活,允许在不同的数据大小上进行算术运算,因此可以选择合适的大小。 - Mike Seymour

0
我知道“自然大小”是指特定硬件最有效处理的整数宽度。
这是一个很好的开始。
“自然大小”的定义就在上面的段落中,没有其他因素决定它。
按照定义,这样做是最有效的。
这是因为C语言的定义如此。没有深层次的架构原因(当C语言被发明时可能存在一些)。
当对长整型进行算术运算时,一堆电子穿过脏沙子并遇到一堆空洞。(不,真的。问一个含糊的问题...)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接