从我从得到的回答这个问题,看来C ++继承了这一要求,对于转换short
成int
从C五月我执行算术运算时,挑选你的大脑,以为什么这是用C首先介绍?为什么不做这些操作short
呢?
例如(摘自dyp在评论中的建议):
short s = 1, t = 2 ;
auto x = s + t ;
x
将具有int类型。
从我从得到的回答这个问题,看来C ++继承了这一要求,对于转换short
成int
从C五月我执行算术运算时,挑选你的大脑,以为什么这是用C首先介绍?为什么不做这些操作short
呢?
例如(摘自dyp在评论中的建议):
short s = 1, t = 2 ;
auto x = s + t ;
x
将具有int类型。
int
不提升为long
(maxint + maxint> maxint)。
x
类型的规则int
在C和C ++中却完全不同... ;-)
Answers:
如果我们看一下国际标准的理由-编程语言-C6.3.1.8
通常的算术转换”部分中,它会说(强调我的前进):
这些转换的标准中的规则是对K&R中的那些规则的略微修改:这些修改包含添加的类型和值保留规则。添加了显式许可证,以比绝对必要的“更广泛”的类型执行计算,因为这有时会产生更小和更快的代码,更不用说正确答案了。只要获得相同的最终结果,也可以按照规则使用“更窄”的类型执行计算。显式强制转换始终可以用于获取所需类型的值
第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。
在某些情况下,这可能会产生一些出乎意料的结果,因为无符号和较大的带符号类型之间隐式转换的不一致行为表明,还有更多类似的示例。尽管在大多数情况下这会导致操作按预期进行。
int
,则该表达式的行为就像其操作数也被强制转换并且对较小的类型。没有确定的情况会与该规则相抵触,但是某些编译器可能会以提升为借口来推断像这样的语句x*=y;
(带有两个变量unsigned short
)承诺x
不能超过2147483648 / y。
int x = 1234
和char *y = &x
。1234
is的二进制表示形式00000000 00000000 00000100 11010010
。我的机器是小字节序的,因此它将其反转并存储在内存中11010010 00000100 00000000 00000000
LSB首先出现。现在主要部分。如果我使用printf("%d" , *p)
。printf
将读取第一个字节11010010
只输出-46
,但11010010
就是210
为何还打印-46
。我真的很困惑,我想一些char到整型促销正在做一些事情,但我不知道。
它不是语言的功能,而只是对运行代码的物理处理器体系结构的限制。int
C语言中的打字机通常是标准CPU寄存器的大小。更多的硅占用更多的空间和更多的功率,因此在许多情况下,只能对“自然大小”数据类型进行算术运算。并非普遍如此,但是大多数体系结构仍然有此限制。换句话说,当将两个8位数字相加时,处理器中实际发生的是某种类型的32位算术运算,然后是简单的位掩码或另一种适当的类型转换。
short
char
标准类型的“存储类型”考虑了类型和类型,即可以用于节省空间的子范围,但这些子范围不会给您带来任何速度,因为它们的大小对于CPU而言是“不自然的”。
在某些CPU上,这是不正确的,但是好的编译器足够聪明,可以注意到,例如,如果您将一个常量添加到一个未签名的char中,然后将结果存储回一个未签名的char中,则无需遍历 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:
在这里您可以看到使用了未签名的字符加法指令(addb
)。
如果在短整数之间进行计算并将结果存储在短整数中,也会发生同样的情况。
链接的问题似乎很好地涵盖了这一点:CPU却没有。32位CPU为32位寄存器设置了其本机算术运算。处理器更喜欢以自己喜欢的大小工作,对于这样的操作,将较小的值复制到本机大小的寄存器中很便宜。(对于x86体系结构,将32位寄存器命名为好像它们是16位寄存器的扩展版本(eax
to ax
,ebx
tobx
等等);请参见x86整数指令)。
对于某些极其常见的操作,尤其是矢量/浮点运算,可能会有专门的指令对不同的寄存器类型或大小进行操作。对于较短的内容,(最多)16位零填充几乎没有性能成本,添加专用指令可能不值得在芯片上花费时间或空间(如果您想真正了解原因,我是不确定他们会占用实际空间,但确实会变得更复杂)。
short s=1, t=2; auto x = s+t;
然后x
是一个int
。