C语言符号位补码要变吗,补码与符号位取反

补码与符号位取反

先来一个 C 语言的小例子:

#include #include int main(void)

{

int16_t n = -1;

n &= 0x7FFF; // 按位与

printf("%d", n); // 这里输出什么?

return 0;

}

对于16位的整数 n ,按位与运行将最高位设置为0(符号位),得到的结果却不是 1 ,结果是 32767 。

原因在于有符号整数的实现方式。

有符号整数,最容易想到的方式是在最高位加一个符号位,0表示整数,1表示负数,其它位不变(保留原始值),也即是原码方式。但这个方式有一个问题,存在两个0,正0和负0,在计算时需要先判断符号位,然后才能决定用加法还是减法,机器计算不便。

另外一个方法是负数全部按位取反,也就是反码方式。这个运算就相对简单了,进行加法时,按位计算,0和0为0,0为1为1,1和1为0并产生进位,最高位有进位时,结果要加1,减法可处理为其负数的加法。但还是有点问题,还存在两个0,正0和负0。

问题是出现负数上,那么把负数的反码 + 1 ,不就把负0去掉了吗?还真的是这样,而同时负数比整数能多表示一个数(这是基于同余的)。

严格的表达为:

对于位数为 n 的整数,其补码 [x]补 为:(2^n + x) mod 2^n ,

表示的范围为 -2^(n-1) <= n < 2^(n-1) ,注意正数最大为 2^(n-1)-1

即:

当 0 <= x < 2^(n-1) 时,

[x]补 = x 的原码

当 -2^(n-1) <= x < 0 时,

[x]补 = 2^n + x 的原码。

而经验上,可看作负数的补码为其反码加1(特殊数 -2^(n-1) ) 的反码 :

x < 0 时:

[x]补 = [x]反 + 1

特殊数 [ -2^(n-1) ] = 100...0

它的加法处理非常简单,符号位也可以运行,

[x+y]补 = (2^n + x + y) mod 2^n = ((2^n + x) + (2^n + y)) mod 2^n = [x]补 + [y]补

[x-y]补 = (2^n + x - y) mod 2^n = ... = [x]补 + [-y]补

现在回到原来的问题,对于16位 -1 ,其补码为:

[-1]补 = [-1]反 + 1 = 0xFFFFF

按位与去掉符号位,得到的是 0x7FFF 也就是16位整数最大的正数( 2^15 - 1) 32767。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值