day*_*oli 70 c c++ int short integer-promotion
从我从得到的回答这个问题,看来C++继承了这一要求,对于转换short成int从C.执行算术运算时,我可以挑你的大脑,以为什么这是用C首先介绍?为什么不做这些操作short呢?
例如(取自评论中的dyp建议):
short s = 1, t = 2 ;
auto x = s + t ;
Run Code Online (Sandbox Code Playgroud)
x将具有int类型.
Sha*_*our 39
如果我们在常用算术转换部分中查看国际标准编程语言-C的基本原理,那么(强调我的未来):6.3.1.8
这些转换的标准中的规则是对K&R中的规则的略微修改:修改适应添加的类型和保留值规则.添加显式许可证以在"更广泛"的类型中执行计算,而不是绝对必要的,因为这有时会产生更小更快的代码,更不用说更频繁的正确答案了.只要获得相同的最终结果,也可以通过as if规则以"较窄"类型执行计算.可以始终使用显式转换来获得所需类型的值
节6.3.1.8从C99草案标准涵盖了通常的算术转换施加到算术表达式的操作数的例如部分6.5.6加法运算符表示:
如果两个操作数都具有算术类型,则对它们执行通常的算术转换.
我们在第6.5.5节" 乘法运算符"中也找到了类似的文本.在短操作数的情况下,首先从6.3.1.1节布尔,字符和整数中应用整数提升,其中:
如果int可以表示原始类型的所有值,则该值将转换为int; 否则,它将转换为unsigned int. 这些被称为整数促销.48)所有其他类型的整数提升不变.
关于整数促销6.3.1.1的基本原理或国际标准编程语言-C部分的讨论实际上更有趣,我将有选择地引用b/c它太长而无法完全引用:
实施属于两个主要阵营,其特点可能是无保留的保留和价值保留.
[...]
该无符号保留的做法呼吁促进两个较小的无符号类型unsigned int类型.这是一个简单的规则,并产生一种独立于执行环境的类型.
该值保存方法要求促进这些类型有符号整数,如果该类型可以正确表示原始类型的所有值,否则为促进这些类型unsigned int类型.因此,如果执行环境将short表示为小于int的东西,则unsigned short变为int; 否则它变成unsigned int.
在某些情况下,这会产生一些意想不到的结果,因为无符号和更大的有符号类型之间的隐式转换的不一致行为表明,还有更多这样的例子.虽然在大多数情况下,这会导致操作按预期工作.
Pho*_*non 22
它不是语言的一个特征,因为它是代码运行的物理处理器体系结构的限制.intC中的typer通常是标准CPU寄存器的大小.更多的硅占用更多空间和更多功率,因此在许多情况下,算术只能在"自然大小"数据类型上完成.这并非普遍适用,但大多数架构仍然存在此限制.换句话说,当添加两个8位数时,处理器中实际发生的是某种类型的32位算术,然后是简单的位掩码或其他适当的类型转换.
650*_*502 18
short和char类型被标准类型的"存储类型"所考虑,即可以用来节省一些空间的子范围,但是它们不会以任何速度购买,因为它们的大小对于CPU来说是"不自然的".
在某些CPU上,这不是真的,但是好的编译器足够聪明地注意到,如果你例如向unsigned char添加一个常量并将结果存储回unsigned char中,那么就不需要进行unsigned char -> int转换了.例如,使用g ++为内部循环生成的代码
void incbuf(unsigned char *buf, int size) {
for (int i=0; i<size; i++) {
buf[i] = buf[i] + 1;
}
}
Run Code Online (Sandbox Code Playgroud)
只是
.L3:
addb $1, (%rdi,%rax)
addq $1, %rax
cmpl %eax, %esi
jg .L3
.L1:
Run Code Online (Sandbox Code Playgroud)
您可以在其中看到使用unsigned char addition指令(addb).
如果您在短整数之间进行计算并将结果存储为短整数,则会发生同样的情况.
链接的问题似乎很好地涵盖了它:CPU没有.32位CPU的本机算术运算设置为32位寄存器.处理器更喜欢以自己喜欢的尺寸工作,对于这样的操作,将一个小值复制到本机大小的寄存器是很便宜的.(对于x86架构,32位寄存器被命名为它们是16位寄存器的扩展版本(eaxto ax,ebxto bx等);请参阅x86整数指令).
对于一些非常常见的操作,特别是向量/浮点运算,可能存在对不同寄存器类型或大小进行操作的专用指令.对于类似短路的内容,使用(最多)16位零填充具有非常小的性能成本,并且添加专用指令可能不值得在芯片上花费时间或空间(如果您想真正了解原因;我是不确定他们会占用实际空间,但它确实变得更加复杂).