C++ C++;从无符号到有符号的隐式数据类型转换
我知道较低的数据类型被转换为较高的数据类型(例如int->unsigned int->float->等),但我不确定以下几点:C++ C++;从无符号到有符号的隐式数据类型转换,c++,types,C++,Types,我知道较低的数据类型被转换为较高的数据类型(例如int->unsigned int->float->等),但我不确定以下几点: int var = 5u - 10; // var = -5 auto var = 5u - 10; // var = 4294967291 5u是无符号的,但在第一种情况下,为什么-10(有符号整数)不转换为无符号值,而在第二种情况下它转换为无符号值?在第一种情况下,有符号的值不会转换为无符号的值,这对我来说是很奇怪的首先,因为您使用了auto,编译器将在第二个示例
int var = 5u - 10; // var = -5
auto var = 5u - 10; // var = 4294967291
5u是无符号的,但在第一种情况下,为什么-10(有符号整数)不转换为无符号值,而在第二种情况下它转换为无符号值?在第一种情况下,有符号的值不会转换为无符号的值,这对我来说是很奇怪的首先,因为您使用了
auto
,编译器将在第二个示例中选择unsigned
有符号和无符号数字在内部以相同的方式存储。正是打印数字时对数字的解释方式产生了不同[在比较中,由于“负号”有符号数字小于0,其中无符号数字不能小于零]——检查有符号数字是否为“负号”,并将其打印为负号和否定的原始数字。无符号数字只被视为打印时的内部表示形式
因此,您看到的值只是相同数字的两种不同表示形式,分别是有符号和无符号 没有“带符号整数文字”:5u-10
实际上是5u减去10
(减法的)结果是无符号的,并进入溢出,结果是“比溢出0少5个数字”(4294967291=232-5)
第一条语句初始化一个int
,因此无符号编译时常量被重新解释为int。结果是正确的(-5),因为您的硬件使用2s补码算法。(-5和4294967291是相同的32位模式)
第二条语句初始化一个由文本推断其类型的变量。而且它是无符号的
两个示例的右侧完全在无符号类型的域中工作。也就是说,您的两个表达式5u-10
的行为相同,这并不奇怪,因为它们是相同的。在这两种情况下,5u-10
表达式中都没有到int
的转换(您似乎错误地假设了这一点)
表达式5u-10
始终在无符号类型的域中求值,并生成等于UINT_MAX+1-5
的无符号结果。在第一次初始化中,您试图将该值强制放入int
类型的变量中,这会导致实现定义的行为溢出。在您的例子中,您的实现的行为使得var
获取的值-5
。换言之,在var
中产生不同的值
第二种情况下,表达式的类型(即,再次,代码>未签名< /代码>)成为变量的类型,它用无符号值初始化,没有溢出。
< P>在C和C++中,在绝大多数情况下,表达式的类型是由表达式本身决定的,不考虑它出现的背景int var = 5u - 10;
5u
属于无符号整数类型
<代码>10属于int
类型。-
运算符的规则导致将int
参数转换为无符号int
,使表达式等效于5u-10u
。结果是UINT_MAX+1-10
,这是一个非常大的数字。初始化隐式地将其从无符号整数
转换为有符号整数
。由于该值(几乎可以肯定)不能表示为int
,因此转换的结果由实现定义。在几乎所有现有的实现中,转换只是将无符号表示重新解释为一个有符号值,结果是-5
。(这适用于对负值使用2的补码表示的系统;由此产生的有符号/无符号转换的简单性是2的补码如此广泛使用的原因之一。)
注意,var
不可能有值4294967291
;int
在您的系统上可以保存的最大值(可能)是2147483647
auto var = 5u - 10;
5u-10
的计算方法与之前相同,从而在系统上产生UINT_MAX+1-5
或4294967291
的unsigned int
结果。auto
表示var
采用表达式的类型,unsigned int
,因此不执行任何转换。(在具有16位int
的系统上,结果将是65531
)
在回答您的问题时,常量
10
在这两种情况下都从int
转换为unsigned int
。5u-10
根据C标准计算为unsigned int
。在这两种情况下,减法的结果都是unsigned
,但在第一种情况下,结果将转换为目标类型。因此,4294967291
被转换为-5
@Praetorian你是对的,把它当作一个回答,我会标记为接受。我想你发明了这种所谓的继承权类型conversions@LightnessRacesinOrbit我对你的尊敬是相互的。