C语言之按位取反~(七十一)

news/2024/11/20 19:46:52/
  1. 计算机存储数据基本知识

  • 计算机中二进制数包括(正数和负数)是以补码形式存储。

  • 符号位:补码的最左侧首位是符号位,0表示正数,1表示负数。

二进制有三种形式:原码、反码、补码。

  • 正数的补码和反码:是正数本身(原码)。

  • 负数的反码:符号位不变(是1),其余位按位取反,不用加一。

  • 负数的补码:符号位不变(是1),先按位取反,再加一。(即是反码加一)

在计算机内存中,负数以补码形式存在(即取反,再加一)。

  • 计算机并不直接存储二进制原码,而是存储二进制的补码。正数的补码就是原码。比如1,原码0000 0001,补码也为0000 0001。就存储的是原码0000 00001.

  • 而计算机不直接存储负数,而是存储负数的补码,负数的补码计算规则是"符号位不变,原码取反再加一"。

例如:-1怎么存储的?

原码1000 0001

取反1111 1110,

加一1111 1111

1111 1111就是-1的二进制补码。

当负数要输出给别的程序用的时候怎么办呢?总不能把存储的补码给别人的吧?给人用之前需要将补码逆向再转换成原码,否则数据就不对了。

负数转换补码的规则:取反,再加一,符号不变。

那么:

补码转换原码的规则:符号不变,先减一,再取反。

这样就得到原码,可以输出了。

  1. 将正数和负数按位取反(~)

特别注意:

"~"符号取反的用法,场景也不一样,同样是"~"符号,有的是求反码,有的是求补码,所以要搞清楚。

举两个例子说明:

<1>.代码示例一
#include <stdio.h>int main(){int a = 0;printf("~0 = %d\n",~a);a = 1;printf("~1 = %d\n",~a);a = 2;printf("~2 = %d\n",~a);a = -1;printf("~(-1) = %d\n",~a);a = -2;printf("~(-2) = %d\n",~a);
}

打印:

~0 = -1
~1 = -2
~2 = -3
~(-1) = 0
~(-2) = 1
  • ~0步骤

步骤1:首先计算出0的补码,即它本身

步骤2:因为0的补码是负数,所以要还原其原码在输出;

0的补码和反码是他本身,再对0按位取反,就变成1111 1111,因为最高位为1,所以为负数,负数是以补码的形式存储,所以输出时要转换成正确的原码。

因为原码转补码的规则是:先取反,再加一

所以补码转原码的规则是:先减一,再取反。

步骤1:首先计算出0的补码,即它本身
0的原码的补码是他本身:
0000 0000步骤2:因为0的补码是负数,所以要还原其原码在输出
~0:即所有位数,按位取反
1111 1111当你要输出的时候,编译器发现最高位符号位是1,这个数是个负数,而负数在计算机里面是用补码存储的,所以此时计算机认为这个1111 1111是补码,它要转换成原码输出,于是先减去1,除了符号位不变,其他位全部取反。因为原码转补码的规则是:先取反,再加一
所以补码转原码的规则是:先减一,再取反。
减一操作:
1111 1110取反操作
1000 0001 = -1

  • ~1步骤

步骤1:首先计算出1的补码,即它本身

步骤2:因为1的补码是负数,所以要还原其原码在输出;

因为原码转补码的规则是:先取反,再加一

所以补码转原码的规则是:先减一,再取反。

步骤1:首先计算出1的补码,即它本身
1的原码的补码是他本身:
0000 0001步骤2:因为1的补码是负数,所以要还原其原码在输出;
~1的反码:即所有位数,按位取反
1111 1110如果要输出打印,此时编译器发现其为最高位为1,是个负数,负数在计算机里面是用补码存储的,所以此时计算机认为这个1111 1110是补码,它要转换成原码输出,于是先减去1,除了符号位不变,其他位全部取反。减一操作:
1111 1101取反操作
1000 0010 = -2
  • ~(-1)步骤

步骤1:首先计算出-1的补码(因为负数在计算机中以补码形式存在)

步骤2:再对-1的补码按位取反

步骤1:首先计算出-1的补码
-1的原码:
1000 0001-1的反码:即按位取反(负号不变)
1111 1110加一
1111 1111步骤2:再对-1的补码按位取反,包括符号位
~(1111 1111) =0000 0000 = 0 
  • ~(-2)步骤

步骤1:首先计算出-2的补码因为负数在计算机中以补码形式存在)

步骤2:再对-2的补码按位取反

步骤1:首先计算出-2的补码因为负数在计算机中以补码形式存在)
-2的原码:
1000 0010-2的反码:即按位取反(负号不变)
1111 1101加一
1111 1110步骤2:再对-2的补码按位取反
0000 0001 = 1

<2>.代码示例二:按位取反参与多项运算
#include <stdio.h>  int flag = 0x104; //0000 0001 0000 0100  int flag2 = 0x04;printf("flag2 = %#x\n",flag2);printf("~flag2 = %#x\n",~flag2);int b = flag & ~flag2;printf("b = %#x\n",b);return 0;
}

打印:

flag2 = 0x4
~flag2 = 0xfffffffb
b = 0x100

  • 求flag & ~flag2
1.flag = 0x104
二进制原码:
0000 0001 0000 0100  2.flag2 = 0x04
二进制原码:
0000 0000 0000 0100~flag2(按位取反):
1111 1111 1111 1011flag与上flag2的反码0000 0001 0000 0100  1111 1111 1111 1011
=    0000 0001 0000 0000 = 0x100所以b = 0x100,和计算机打印的一样。


http://www.ppmy.cn/news/34780.html

相关文章

四级数据库工程师 刷真题错题整理(三)数据库原理

1.数据模型是对现实世界进行抽象的工具&#xff0c;它按算机系统的观点模于提数据库系统中信息表示和操作手段的形式框架&#xff0c;主要用于 DBMS 的实现&#xff0c;是数据库系统的核心和基础。其中&#xff0c;数据操作是对数据间的动态行为。 2.数据库的型是稳定的&#…

并查集、并查集+离线、并查集+倒叙回答

文章目录并查集[200. 岛屿数量](https://leetcode.cn/problems/number-of-islands/)[721. 账户合并](https://leetcode.cn/problems/accounts-merge/)并查集 离线计算[1697. 检查边长度限制的路径是否存在](https://leetcode.cn/problems/checking-existence-of-edge-length-l…

SpringCloud学习笔记(一)认识微服务

一、微服务技术栈 二、单体架构和分布式架构的区别 1、单体架构&#xff1a; 将业务的所有功能集中在一个项目中开发&#xff0c;打成一个包进行部署 优点&#xff1a;架构简单&#xff0c;部署成本低缺点&#xff1a;耦合度高 2、分布式架构&#xff1a; 根据业务功能对系统…

【周末闲谈】文心一言,模仿还是超越?

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️周末闲谈】 周末闲谈 ✨第一周 二进制VS三进制 文章目录周末闲谈前言一、背景环境二、文心一言&#xff1f;(_)?三、文心一言的优势&#xff1f;&#x1f617;&#x1f617;&#x1f617;四、文心一…

Web站点性能优化经验分享

之前负责IT团队项目管理工作&#xff0c;手里有几套业务站点。其中一个站点被业务吐槽比较严重&#xff0c;主要涉及功能模块缺失、站点性能差会出现卡死的现象&#xff0c;同时也被旁边的项目团队埋怨调用我们的接口会比较慢&#xff0c;甚至超时的情况。 鉴于业务压力&#x…

E - 积木画(状态压缩DP)

E - 积木画&#xff08;状态压缩DP&#xff09; 1、问题 E - 积木画 2、分析 这道题很明显是一道DP题&#xff0c;而且是一个简化版的状态压缩DP。 &#xff08;1&#xff09;状态表示 f[i][j]f[i][j]f[i][j]表示前面i−1i-1i−1已经摆好&#xff0c;并且第iii列的状态是j…

【数据结构与算法】什么是双向循环链表?以及实现过程

文章目录前言&#xff1a;一、相关概念二、实现过程三、总结前言&#xff1a; 线性表是我们最常用的一种数据结构&#xff0c;线性表包含顺序表和链表&#xff0c;顺序表典型应用就是我们常用的ArrayList&#xff0c;链表的典型应用其中就有我们常用的LinkedList。LinkedList他…

【C语言初阶】循环语句

文章目录&#x1f490;专栏导读&#x1f490;文章导读&#x1f337;什么是循环&#x1f337;while循环&#x1f337;do while循环&#x1f337;for循环&#x1f337;循环结构中的break与continue&#x1f33a;break&#x1f33a;continue&#x1f337;goto语句&#x1f490;专栏…