继续有符号与无符号混合运算

前面记录一篇,关于有符号与无符号的混合运算,会有一些意想不到的结果

那么,我们是否可以“负负得正”呢?

什么情况下是不行的?

首先,不要被绕晕。

这是前提: 所有的无符号与有符号运算,都是先转成无符号运算的。结果返回 无符号,

那么,理论结果如果本身就是正数的,那实际就应该是正常的

如果结果不是正数的,那么是负数的无符号形式(最高位=1,其他位取反)

为了验证效果,(就验证加/减/乘/除),写段代码试试:

    int a = -20;
    unsigned int b = 10;

    //保持原始结果
    cout << "a+b=" << a + b << endl;    //希望:-10
    cout << "a*b=" << a * b << endl;     //希望:-200
    cout << "a-b=" << a - b << endl;       //希望:-30
    cout << "a/b=" << a / b << endl;       //希望:-2

    cout << "-a-b=" << -a - b << endl;     //希望:10
    cout << "-b+a=" << -b + a << endl;   //希望:-30

    //对结果进行强转
    cout << "a+b=" << (int)(a + b) << endl;
    cout << "a*b=" << (int)(a * b) << endl;
    cout << "a-b=" << (int)(a - b) << endl;
    cout << "a/b=" << (int)(a / b) << endl;

    cout << "-a-b=" << (int)(-a - b) << endl;
    cout << "-b+a=" << (int)(-b + a) << endl;

实际情况呢?

 

a+b是个无符号的结果,通过强转之后,是-10,可以负负得正,一般可控范围

a*b是个无符号的结果,通过强转之后,是-200,可以负负得正,一般可控范围

a-b是个无符号的结果,通过强转之后,是-30,可以负负得正,一般可控范围

a/b是个无符号的结果,通过强转之后,是429496727,不可以负负得正,属于不可控范围。

那么为什么只有除法不行了呢?

这个还是得从原理讲起,首先,乘法 跟 除法 都是通过移位来解决的

乘法是 左移

除法是 右移

然后,再看下,负数表达形式(以32位系统为例)。

-32 如果是无符号的话,是这样的:

 

如果是64bit,那么前面再多8个F

运算乘法 与 除法 之前,都先转 成 无符号的。

乘法,左移,之后,最高位仍然为1,当然前提数据不能溢出的情况,此时如果对结果再进行强转回来,至少符号位还是正常的

除法,右移,之后,最高位补0,那么就丢失了符号位,哪怕对结果再进行强转回来,也是由于缺少符号位,导致最后数据仍然不对!

int a = -32;
unsigned int b = 16;

//此时会输出什么
a += b;
cout << "a += b   a=" << a << endl;    

//此时会输出什么
a /= b;
cout << "a /= b   a=" << a << endl;

 实际结果:

 

 解释:

a是有符号,b是无符号,先a要转换成无符号,然后再跟b计算,最后由于a是有符号的,结果又转换成有符号,结果符合预期

第二种情况:也是这个步骤,只不过除法用移位方式实现,一旦最高位移掉之后,就不是想要的数据

-a - b,是个另类,-a的优先级,要高于 “减法” 运算符,因此,要先处理 -a 而不是先转成 无符号

           那也说得通:-a = 20, 无符号之后,仍然 20  ;20 - 10 = 10 ,没毛病

最后结论:

1. 如果没有除法的话,无符号跟有符号运算,可以仅对结果进行强转。(前提结果不能溢出)(不推荐这样做,推荐第2种做法)

2. 如果有除法,必须先给无符号转换成有符号的,再计算。

补充下,实际代码的一些风险点:

 

这个是没有问题的,但风格不好

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值