2013-02-11 130 views
3

我知道较低的数据类型被浇铸到更高的数据类型(如int - >无符号整型 - >浮 - >等),但我不能确定如下:C++从无符号的隐式数据类型转换为带符号的

int var = 5u - 10; // var = -5 
auto var = 5u - 10; // var = 4294967291 

5u是无符号的,但在第一种情况下,为什么-10(有符号整数)没有转换为无符号值,而在第二种情况下呢?在第一种情况下,有符号值不会转换为无符号值,对我来说这是奇数

+3

根据C标准,'5u-10'计算为'unsigned int'。 – sgarizvi 2013-02-11 17:51:57

+3

C或C++?选一个。 – 2013-02-11 17:54:41

+7

在这两种情况下,减法的结果都是'无符号',但在第一种情况下,结果将转换为目标类型。因此'4294967291'被转换为'-5' – Praetorian 2013-02-11 17:55:12

回答

3

没有“有符号整数字面量”:5u - 10实际上是从5u中减去10。

(的减法)的结果是无符号的,并进入溢出,给出作为结果(4294967291 = 2 -5)

第一条语句初始化“比飞越0少5个号码”一个int,因此无符号编译时间常数被重新解释为int。结果是正确的(-5),因为你的硬件使用二进制补码算术。 (-5和4294967291是相同的32位模式)

第二条语句初始化一个变量,该变量的类型由文字推断。它是unsigned

2

首先,因为您使用的是auto,编译器会在第二个示例中选择unsigned

有符号和无符号数字在内部以相同的方式存储。这只是数字在打印时被解释的方式,它会产生变化[并且在比较中,因为'负'有符号数字小于0,其中无符号数字不能小于零] - 签名数字被检查如果它们是“负值”,并打印为负号和否定的原始号码。无符号数字只被视为打印时内部表示形式变成的内容。

所以你看到的值只是相同数字的两个不同表示 - 分别为有符号和无符号。

2

的右侧你的例子完全工作在的域中,无符号的类型。即你的两个表情5u - 10表现相同,这并不奇怪,因为它们是相同的。在这两种情况下,都没有转换为int(因为您似乎错误地假设)在5u - 10表达式中。

表达式5u - 10始终在无符号类型的域中进行评估并生成等于UINT_MAX + 1 - 5的无符号结果。在第一次初始化时,您尝试将该值强制为int类型的变量,这会导致实现定义的行为发生溢出。在你的情况下,你的实现表现为var获得值-5。换句话说,在var中以-5结尾的事实在抽象C++语言领域没有明确的解释。你观察到的结果只是你的编译器的一个怪癖。在其他一些编译器中,第一次初始化可能会在var中产生不同的值。

在第二种情况下,表达式的类型(也就是unsigned)变成变量的类型,该变量使用无符号值进行初始化,没有任何溢出。

1

在C和C++中,在绝大多数情况下,表达式的类型是从表达式本身确定的,而不考虑表达式的上下文。

int var = 5u - 10; 

5uunsigned int类型; 10类型为int-运算符的规则会导致int参数转换为unsigned int,从而使表达式等效于5u - 10u。结果是UINT_MAX + 1 - 10,这是一个非常大的数字。初始化将其从unsigned int隐含转换为signed int。由于该值(几乎肯定)不能表示为int,因此转换的结果是实现定义的。在几乎所有现有的实现中,转换只是重新解释无符号表示,就好像它是一个有符号值,导致-5。 (这适用于使用二进制补码表示负值的系统;由此产生的有符号/无符号转换的简单性是二进制补码广泛使用的原因之一。)

请注意,它不可能用于var具有值4294967291; int可以容纳在您的系统上的最大值是(可能)2147483647

auto var = 5u - 10; 

5u - 10作为评估之前以同样的方式,导致UINT_MAX + 1 - 5,或者4294967291您的系统上的unsigned int结果。 auto表示var采用表达式的类型unsigned int,因此不执行转换。 (在16位int的系统,其结果将是65531

在回答你的问题,不断10int转换为unsigned int在这两种情况下

相关问题