当无符号数与有符号数一起玩耍时

发布于:2021-09-23 16:54:08

前言:
C/C++中的无符号数里,没有了符号位的概念,因此也没有溢出可言,算数运算符中如果一个操作数是有符号数如int类型,另一个操作数是无符号数如unsigned int类型,那么无符号数会被转换为无符号数进行运算,因此也不会发生溢出【 因为C语言规定无符号整数运算不会溢出,如果结果大于所能表示的最大值M,则模(M+1)即无符号整数相加不会溢出,对于超出表示范围的部分直接截去了 】。但是,当两个操作数都是有符号数时,溢出就有可能发生了。


1, 表达式中的数据如果遇到更高级别的数据,就会自动转换为高级别的数据类型。如果我们“定义”一个数据类型表示的范围越大,这个类型的级别越“高”。那么按照从高到低的顺序排列,应该是:
long double > double > float > unsigned long long > long long > unsigned long > long > unsigned int > int
(注意,有的系统中,long和int大小相同,此时 unsigned int 的等级就会高于long)。


int fun()
{
unsigned int a = 10;
int b = -100;
int c;
(a+b > 0) ? (c=1) : (c=0);
return c;
}

以上答案是1,是不是觉得很奇怪呢? 哈哈,这就是有关的一个代码小陷阱了,当无符号数和有符号数一起运算时,有符号数也会被自动隐式转换为无符号数,因此这个时候对于 a+b 中 b 的值被当做一个很大的整数进行计算,所以得到的结果是大于0的;


2,整数溢出时如何判断溢出


// 方法1: 将进行运算的那几个有符号数强制类型转换为无符号数:
int AddTwo(int a, int b)
{
// INT_MAX为有符号整型的最大值,是编译器中预定义的常量,值为2^31-1,即0X7FFFFFFF
if((unsigned int)a + (unsigned int)b > INT_MAX)
exit(-1); // 溢出则退出该进程
else
return a+b; // 正常返回结果
}


// 方法2: 不需要用到强制类型转换为无符号类型的可行方法
int AddTwo(int a, int b)
{
if(a > INT_MAX -b)
exit(-1); // 溢出则结束该进程
else
return a+b;
}

注意:
1:float, double 都是有符号的。
2:float, double 不能用 signed, unsigned 修饰 。
3:有符号数的最高位(31位)为符号位,最高位为0的时候,表示正,为1的时候表示负。运算时,符号位不参加运算,但是如果两个数相加,30位需要进1时,那么即表示溢出。


思考:方法一中,当一个为正数,一个为负数,那么负数经过unsigned int 的强制类型转换为一个很大的正数,这样正数加负数本来而言是不会溢出的,但这样看的话不是就超出了INT_MAX了吗?
答案就在前言的中括号里面的句子里,稍稍说一下是因为无符号整数相加是不会有溢出可言的;


小结:
1)无符号数和有符号一起运算时,有符号数会被隐式强制类型转换为无符号数进行运算。
2)对于有符号数运算的溢出判断问题可以善于利用C语言中规定的无符号数运算不会溢出的规定。
预见下一篇文章的内容:


是不是很迫不及待的想写atoi,大整数运算的代码了,嗯嗯,反正我自己是很期待了,下一篇文章实现一下这方面的内容;


以上代码经经过验证,如果有疑问或错误欢迎讨论指正,相互学*进步,谢谢


参考资料:
《C缺陷与陷阱》
http://blog.csdn.net/lazy_tiger/article/details/2107834
http://m.blog.csdn.net/blog/bichenggui/4734040
http://bbs.chinaunix.net/thread-1097996-1-1.html

相关推荐

最新更新

猜你喜欢