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

前言:
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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值