为什么在C和C ++的算术运算之前,一个简短的被转换为int?

从我从这个问题得到的答案看来,C ++inheritance了从C执行算术运算时将short转换为int这一要求。请问您为什么首先在C中引入了这个大脑? 为什么不把这些操作做得short呢?

例如( 从dyp的意见中得到的build议 ):

 short s = 1, t = 2 ; auto x = s + t ; 

x将具有inttypes。

如果我们看6.3.1.86.3.1.8 常用算术转换的 国际标准编程语言C的基本原理 ( 强调我的前进 ):

标准中对这些转换的规则是对K&R中规则的轻微修改:这些修改适应添加的types和保值规则。 显式许可证被添加到执行“更宽”types的计算中,而不是绝对必要的,因为这有时会产生更小更快的代码,更不用说正确的答案 。 只要得到相同的最终结果,计算也可以按“规则”的规则进行。 总是可以使用明确的转换来获得所需types的值

C99标准草案第6.3.1.8节涵盖适用于算术expression式操作数的常用算术转换 ,例如第6.5.6节。 加法运算符说:

如果两个操作数都具有算术types,则会对其执行通常的算术转换

我们在6.5.5乘法运算符中也find类似的文字。 在操作数较短的情况下,首先应用6.3.1.1节的布尔,字符和整数中的整数提升

如果int可以表示原始types的所有值,则该值将被转换为int; 否则,它被转换为一个无符号的整数。 这些被称为整数促销48)所有其他types均不受整数升级的影响。

关于整数促销理由或国际标准程序devise语言-C6.3.1.1节的讨论实际上更有趣,我将有select地引用B / C,

实施分为两大阵营 ,可能被视为无保留和保值

[…]

无符号保留方法要求将两个较小的无符号types提升为unsigned int。 这是一个简单的规则,并产生一个独立于执行环境的types。

值保留方法要求将这些types提升为有符号整数,如果该types可以正确表示原始types的所有值,否则将这些types提升为无符号整型。 因此,如果执行环境表示short小于int,则unsigned short变成int; 否则它变成unsigned int。

在一些情况下,这可能会有一些意想不到的结果,因为在unsigned和更大的signedtypes之间的隐式转换的不一致行为表明,有更多的例子。 尽pipe在大多数情况下,这会导致操作按预期工作。

这不是语言的特征,而是代码运行的物理处理器体系结构的限制。 C中的int typer通常是标准CPU寄存器的大小。 更多的硅占用更多的空间和更多的功率,所以在很多情况下,算术只能在“自然尺寸”数据types上进行。 这并不普遍,但是大多数架构仍然有这个限制。 换句话说,当添加两个8位数字时,处理器中实际发生的是某种types的32位算术,然后是简单的位掩码或其他适当types的转换。

floatshortchartypes被标准的“存储types”所考虑,也就是说可以用来节省一些空间的子范围,但是由于它们的大小对于CPU来说是“不自然的”,所以不会给你带来任何的速度。

在某些CPU上,这是不正确的,但好的编译器足够聪明,可以注意到,如果你将一个常量添加到一个无符号字符并将结果存回一个无符号字符,那么就不需要经过unsigned char -> int转换。 例如用g ++为内部循环生成的代码

 void incbuf(unsigned char *buf, int size) { for (int i=0; i<size; i++) { buf[i] = buf[i] + 1; } } 

只是

 .L3: addb $1, (%rdi,%rax) addq $1, %rax cmpl %eax, %esi jg .L3 .L1: 

在这里你可以看到使用了一个无符号的char加法指令( addb )。

如果您在短整数之间进行计算并以短整数存储结果,则会发生同样的情况。

链接的问题似乎覆盖了很好:CPU没有。 32位CPU的本地算术运算设置为32位寄存器。 处理器更喜欢使用它最喜欢的尺寸,而对于这样的操作,将一个小的值复制到本地大小的寄存器是便宜的。 (对于x86架构,32位寄存器被命名为16位寄存器的扩展版本( eax to axebx to bx等);请参阅x86整数指令 )。

对于一些非常常见的操作,特别是向量/浮点运算,可能会有专门的指令在不同的寄存器types或大小上操作。 对于类似简短的事情,填充(高达)16位零的性能成本非常低,添加专门的指令可能不值得在死亡的时间或空间(如果你想得到真正的物理原因,我是不知道他们会采取实际的空间,但它确实更复杂)。