C语言按位取反~的简单理解

学习按位取反时,一直不是很理解,为啥对0取反就是-1,对76取反就是-77,网上有说记住x+(~x)=-1就可以了,可还是有点难懂。所以我来解释一波为啥对0取反就是-1

  1. 十进制数 0 的十六进制表示为 0000 0000
  2. 对其~(取反)后得到 1111 1111
  3. 此时这个值转化为十进制就是255
  4. 此时 255-256=-1

同理 76 的十六进制为 0100 1100,取反后为1011 0011,转为十进制数为179,179-256= -77

这里其实就是有符号数的转化,在8位的范围内(0~255),最大值就只能到255。
当然,对于16位、32位数也适用,大家可以试一试。

扩展知识点

——无符号数中的负数怎么表示

无符号的8位数值中,由于不能为负值,所以-1实际上不能以-1的形式存在(很绕但确实是这样的),实际你看到的显示出来的数值为255,这是为啥呢?
例如下面这样:

#include <stdio.h>
typedef unsigned char U8;//8位无符号数,范围0~255

int main(void)
{
	 U8 u8_num=-1;
	 print("%d\n",u8_num);
	return 0;
}

结果是

255

我们定义了一个8位的无符号数值,所以它的范围是0~255,-1不在这个范围内,所以此时它如何显示?这涉及到负数在计算机中的表示了。

我们知道,在计算机系统中数据都是以补码形式存储的,只不过正数的补码等于反码又等于原码。而负数的补码等于对原码取反加1

那我们求一下-1的补码(8位数值)
原码:1000 0001,(最高位为符号位,为1代表负数,为0代表正数)

反码:1111 1110,(符号位不变,其他位按位取反)

补码:1111 1111,(反码 + 1)

我们看这个补码是不是很熟悉??
没错,这个-1的补码也就是我们无符号数255的原码和补码;

正数的补码等于其本身

这里就有一个疑问,数值的原码首位不是符号位吗?为啥1111 1111却可以表示为正数255呢?

如果你的变量是8位的带符号的数,那么最高位第7位作为符号位用,最高位为0时表示是正数,为1时表示是负数;而无符号数是相对于有符号数而言的,指的是整个机器字长的全部二进制位均表示数值位,相当于数的绝对值。

也就是说无符号数没有符号位,符号位是有符号数玩的把戏。
在无符号数中,1111 1111是255,但在有符号数中,1111 1111就是-1的补码。

所以我们原本是想在一个无符号数中表示一个有符号数(-1),这是不现实的,但最终计算机妥协了,不过是以无符号数的形式(255)表现出来的有符号数(-1)。

关于补码,下面的介绍可以帮助大家了解更详细一点。本文就说这么多吧。

正数的原码=反码=补码。引进补码的作用是为了让计算机更方便做减法。
例如:按时间12个小时来算,现在的准确时间是4点,有一个表显示的是7点,如果要校准时间,我们可以将时针退7-4=3格,也可以向前拨12-3=9格,计算机做减法就可以使-3转化为+9,这样可以简化计算机的硬件设备去做复杂的减法。
所以补码反码就是为了简化减法而来的,将减号化为负数,再将负数化为补码求加法,跟正数没关系。所以不管是正整数还是正小数,原码,反码,补码都全部相同。1

参考文献:


  1. https://zhidao.baidu.com/question/2208490602456362988.html ↩︎

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值