当前位置:  开发笔记 > 编程语言 > 正文

无符号和有符号整数的比较运算

如何解决《无符号和有符号整数的比较运算》经验,为你挑选了2个好方法。

请参阅此代码段

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)作为差异?



1> AnT..:

不同的积分类型之间的二进制操作由所谓的定义的"公共"型内进行通常的算术转换(参见语言规范,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很好.



2> kennytm..:

int32位的典型实现中,转换为a时的-1 unsigned int是4,294,967,295,其确实≥1000.

即使你在一个unsigned世界中对待减法,1000 - (4,294,967,295) = -4,294,966,295 = 1,001这就是你得到的.

这就是为什么gcc当你比较会吐出警告unsignedsigned.(如果没有看到警告,请传递-Wsign-compare旗帜.)


正如litb所说,它与代表性无关.在1s补码机器上,将-1转换为无符号导致UINT_MAX,它不会导致1s'补码位模式被重新解释.2的补码很方便的几种方法之一是C(un)签名转换不会改变位模式.这特别适用于2的补码:对无符号类型的C转换是以模运算的方式定义的,而不是根据位模式定义的.在1s补码上,实现必须做一些实际的工作来提出UINT_MAX.
推荐阅读
贾志军
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有