Git*_*tmo 40 c unsigned signed gcc
请参阅此代码段
int main()
{ 
 unsigned int a = 1000;
 int b = -1;
 if (a>b) printf("A is BIG! %d\n", a-b);
 else printf("a is SMALL! %d\n", a-b); 
 return 0;
}   
这给出了输出:a是SMALL:1001
我不明白这里发生了什么.>运算符如何在这里工作?为什么"a"小于"b"?如果它确实更小,为什么我得到一个正数(1001)作为差异?
AnT*_*AnT 48
不同的积分类型之间的二进制操作由所谓的定义的"公共"型内进行通常的算术转换(参见语言规范,6.3.1.8).在你的情况下,"常见"类型是unsigned int.这意味着int操作数(您的b)将unsigned int在比较之前转换为以及执行减法的目的.
当-1被转换为unsigned int结果是最大可能unsigned int值(同UINT_MAX).毋庸置疑,它将大于你的无符号1000值,这意味着它a > b确实是错误的,a并且确实比较小(unsigned) b.在if你的代码应该下定决心else分支,它是你在实验中观察到的东西.
相同的转换规则适用于减法.你a-b的确被解释为a - (unsigned) b,结果有类型unsigned int.这样的值不能使用%d格式说明符打印,因为%d只能使用有符号值.您尝试打印它会%d导致未定义的行为,因此从C语言的角度来看,您看到的打印值(即使它在实践中具有逻辑确定性解释)完全没有意义.
编辑:实际上,我对未定义的行为部分可能是错的.根据C语言规范,相应的有符号和无符号整数类型范围的公共部分应具有相同的表示(根据脚注31,"可互换性作为函数的参数").因此,a - b表达式的结果是1001如上所述的无符号,除非我遗漏了某些内容,否则使用%d说明符打印此特定无符号值是合法的,因为它属于正范围int.打印(unsigned) INT_MAX + 1时%d未定义,但1001u很好.
ken*_*ytm 14
在int32位的典型实现中,转换为a时的-1 unsigned int是4,294,967,295,其确实≥1000.
即使你在一个unsigned世界中对待减法,1000 - (4,294,967,295) = -4,294,966,295 = 1,001这就是你得到的.
这就是为什么gcc当你比较会吐出警告unsigned有signed.(如果没有看到警告,请传递-Wsign-compare旗帜.)
| 归档时间: | 
 | 
| 查看次数: | 40720 次 | 
| 最近记录: |