C语言无符号数减法

测试代码

void ChkTest(void)
{
    unsigned int cnt1 = 1;
    unsigned int cnt2 = 2;
    unsigned short a = 1;
    unsigned short b=-1;//等价于unsigned short b=0xFFFF;
    unsigned short c=0;
    
    c = a-b;
    printk("cnt1-cnt2=%x %d\r\n",cnt1-cnt2,cnt1-cnt2);
    printk("a-b = 0x%X  a-b = %d c=0x%x\n",a-b,a-b,c);
}

执行结果:cnt1-cnt2=ffffffff -1
a-b = 0xFFFF0002  a-b = -65534 c=0x2

分析首先CPU没有减法操作,需要把减法转为加法运算,

则1-2转为加法操作1+(-2)对应实际正数的补码为自己,负数的补码为其反码+1,

[+1] = [00000000 00000000 00000000 00000001]原 = [00000000 00000000 00000000 00000001]反 = [00000000 00000000 00000000 00000001]补

[-2] = [10000000 00000000 00000000 0000010]原 = [11111111 11111111 11111111 11111101]反 = [11111111 11111111 11111111 11111110]补

1-2= [00000000 00000000 00000000 00000001]+[11111111 11111111 11111111 11111110]=[11111111 11111111 11111111 11111111]

这个结果使用%x输出为实际内存中的数据,

%d输出为转为有符号的结果([11111111 11111111 11111111 11111111]再求补码[10000000 00000000 00000000 00000001 ]);

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

同理a-b=1-(-1)=1+(-(-1))操作转补码:

[+1] = [00000000 00000001]原 = [00000000 00000001]反 = [00000000 00000001]补

[-(-1)]=-0xFFFF, printk("a-b = 0x%X  a-b = %d c=0x%x\n",a-b,a-b,c);这句打印语句隐含了%X和%d是四字节返回值,c是2字节值

则前段计算红色a-b值需要转为4字节运算,而c = a-b;执行2字节的运算(存在截断情况)

扩展四字节[-(-1)] = [-(11111111 11111111) ] =

[10000000 00000000 11111111 11111111) ]原 =[11111111 11111111 00000000 00000000]反 = [11111111 11111111 00000000 00000001]补

1+(-(-1))=[00000000 00000001]+[11111111 11111111 00000000 00000001]=[11111111 11111111 00000000 00000010]

这个结果使用%x输出为实际内存中的数据(0xFFFF0002),

%d输出转为有符号的结果([11111111 11111111 00000000 00000010]再求补码[10000000 00000000 11111111 11111110 ]);

c=0x%x两字节[-(-1)] = [-(11111111 11111111) ] 符号位和数据位重叠,假设扩展为4字节表示,具体值同上,符号位在最高位(这里暂未确认编译器如何处理);

1+(-(-1))=[00000000 00000001]+[11111111 11111111 00000000 00000001]=[11111111 11111111 00000000 00000010],截断后两个字节赋值给c。

这个结果使用%x输出为实际内存中的数据0x0002([00000000 00000010]补码同原码);

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

总结:

1.分析减法需要明确补码的使用方式,不能按照数学常识计算1-2=-1。

2.无符号数和有符号数进行算数运算,先转有符号为无符号,然后运算(可能存在截断情况)。

3.负数实际在内存中是以补码形式存在,%d格式输出的不是存储的原始数据,%x输出的才是内存原始数据。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值