C++ C++;从无符号到有符号的隐式数据类型转换

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->unsigned int->float->等),但我不确定以下几点:

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 >代码中,你最终得到的是<代码> -5 < /> >在抽象C++语言领域没有明确的解释。您观察到的结果只是编译器的一个怪癖。在其他一些编译器中,第一次初始化可能会在
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我对你的尊敬是相互的。