请查看以下代码:
#include <stdlib.h>
#include <stdio.h>
int main()
{
unsigned int a = 1;
unsigned int b = -1;
printf("0x%X\n", (a-b));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
结果是0x2.
我认为整数提升不应该发生,因为"a"和"b"的类型都是unsigned int.但结果打败了我......我不知道原因.
顺便说一下,我知道算术结果应该是2,因为1 - ( - 1)= 2.但是b的类型是unsigned int.将(-1)赋值给b时,b的值实际上是0xFFFFFFFF.它是unsigned int的最大值.当一个小的无符号值减去一个大值时,结果不是我所期望的.
从下面的答案中,我认为溢出可能是一个很好的解释.现在我写了其他测试代码.它证明了溢出的答案是正确的.
#include <stdlib.h>
#include <stdio.h>
int main()
{
unsigned int c = 1;
unsigned int d = -1;
printf("0x%llx\n", (unsigned long long)c-(unsigned long long)d);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
结果是"0xffffffff00000002".这是我期待的.
unsigned int a = 1;
Run Code Online (Sandbox Code Playgroud)
这将初始化a为1.实际上,由于1是型的int,有一个隐含的int-到- unsigned转换,但它是一个简单的转换不改变的值或表示).
unsigned int b = -1;
Run Code Online (Sandbox Code Playgroud)
这更有趣. -1是类型int,初始化隐式将其转换int为unsigned int.由于数学值-1不能表示为a unsigned int,因此转换非常重要.这种情况下的规则是(引用C标准第6.3.1.3节):
通过重复加或减一个可以在新类型中表示的最大值来转换该值,直到该值在新类型的范围内.
当然,只要结果相同,它实际上不必这样做.添加UINT_MAX+1(" 比新类型中可表示的最大值多一个 ")为-1 UINT_MAX.(该添加是以数学方式定义的;它本身不受任何类型转换的影响.)
实际上,分配-1给任何无符号类型的对象是获取该类型的最大值而不必引用其中*_MAX定义的宏的好方法<limits.h>.
因此,假设一个典型的32位系统,我们有a == 1和b == 0xFFFFFFFF.
printf("0x%X\n", (a-b));
Run Code Online (Sandbox Code Playgroud)
减法的数学结果是-0xFFFFFFFE,但这显然超出了范围unsigned int.无符号算术的规则类似于无符号转换的规则; 结果是2.