C语言学习

2023-11-12

目录

原码反码和补码 

原码(true code)

反码(complemental code)

补码(ones-complement code)

溢出的处理

位运算符

移位操作符 << >>

<< 左移

>> 右移

按位操作符 & | ^

& 按位与

| 按位或

^ 按位异

~ 按位反

 

移位操作符的代码实例

求对应值的补码(二进制)


原码反码和补码 

计算机内存储存变量都是通过二进制储存,计算机只看得懂二进制,0(代表低电流),1(代表高电流),通过二进制描述正负数,便诞生了原码的概念;如何实现加减法,为了通过加法实现减法,反码便出现了;针对反码的一些不足,对进行反码改进,补码便诞生了。计算机内存储存变量和进行变量计算都是通过补码,因此原码,反码和补码十分重要。

原码(true code)

原码(true code)是计算机对二进制数定点表示的一种方法,其中在二进制的前面加了一位符号位,0表示整数,1表示负数,0可以用+0和-0表示。

十进制 原码(6个进制位表示)
10 001010
3 000011
0 000000/100000
-3 100011
-10 101010

利用原码可以进行加法运算,但不能通过加法来实现减法运算,用原码进行减法运算需要添加减号模块,实现麻烦。

3+10 = 000011+001010 = 001101 = 13

10-3 = 10 + (-3) = 001010 + 100011 = 101101 = -13 ×

反码(complemental code)

反码是对二进制数表示的方法,它是为了通过加法来实现减法运算而诞生的。正数的反码是它本身,而负数的反码是除了符号位以外,二进制位的0变成1,1变成0得到反码。

十进制数 原码 反码
7 000111 000111
5 000011

000011

0              000000/100000 000000/111111
-3 100011 111100
-5 100101

111010

通过反码,就可以进行减法运算,但不足的是0也有两个对应的反码,而且如果有溢出,需要做+1处理。

22 - 5 = 22+(-5)=010110 + 111010 = 1 010000 = 010000 + 000001 = 010001= 17

其中,红色表示溢出,黄色是溢出的处理,如果二进制有溢出,需要加1,然后舍掉溢出的位置,这样便可以实现减法运算。

反码解决了减法的运算,但是0有两个对应的反码,而且如果溢出时需要处理,可不可以优化呢?

补码(ones-complement code)

补码是反码的延伸,它同样是表示二进制数的一种方法,正数的补码是自己本身,而负数的补码是反码+1,补码就像是反码上加了个补丁,修补了反码的缺点。同时规定0的补码为000000(全0)。

通过补码的补充,0有了唯一对应的二进制,而且不仅可以处理减法运算,也能更方便地处理溢出操作。

22 - 5 = 22+(-5)=010110 + 111011 = 1 010001 = 010001 = 17

其中,红色是溢出位,运用补码进行运算,直接舍弃溢出的数字,保留其余二进制,就是结果。

补码也同时规定 -2^6 = -64的补码为100000,没有六位二进制的原码和反码。补码相对于反码不仅优化了溢出的操作,更解决了0的对应问题,0在反码中只有唯一的二进制与其对应。相比较而言,反码代表的数字比原码和反码都多1个,表示的范围也更大。在计算机系统中,数值一律用补码计算和表示。

(n位二进制) 原码 反码 补码
可表示的个数 2^n-1 2^n-1 2^n
表示范围 -(2^n-1)~(2^n-1) -(2^n-1)~(2^n-1) -2^n~(2^n-1)

C语言中,int类型的变量大小为4个字节,32个比特位,也就是用32位二进制储存,其中第一位是符号位,则int类型的范围是 -(2^31) ~ (2^31-1)

溢出的处理

如果表示的数字超过了范围怎么办,计算机对于溢出的处理类似时钟的转动,如图所示

 对于四位二进制,可表示的范围是-8~7,如果超出了7,则会沿着时钟继续前进。如果超过了1个,则前进1个单位,也就是-8,然后继续转动,加是向右转动,减是向左转动,时钟很好的解决了范围的边界问题。我们在C语言经常看到,当数大到一定程度的时候变成了负数,也是这样的原理。

以上就是计算机关于位的处理,接下来我们来看C语言中的位操作符

位运算符

位运算符均是对补码进行操作,因为计算机对数值的存储就是通过补码存储,而且位运算符只能对整数进行处理,均是双目操作符,即需要两个对象。在C语言中,位运算符主要有 << 左移, >> 右移,^ 异或和~取反操作符,。假设有整数变量 int a = 10;

移位操作符 << >>

<< 左移

a << 2,对a的补码左移两位,<< 对变量的补码进行左移,新上来的位补0,左边溢出的位直接舍掉。a的结果就是a*(2^2),也就是40,左移n位就是乘以2的n次方。

int main()
{
	int a = 10;
	int b = 0;
	b = a << 2; //a<<2,但不改变原来a的值
	printf("a = %d\n", a); // a = 10
	printf("b = %d", b); // b = 40
	return 0;
}

>> 右移

a>>1,将a的补码向右移动1位,如果是正数,则左边补0,负数左边补1,右边溢出的位直接舍弃。>> 是右移操作符,对变量补码进行右移操作。

int main()
{
	int a = -3;
	int b = 0;
	b = a >> 2; //对a的补码向右移动2位
	printf("a = %d\n", a); //a = -3
	printf("b = %d", b); //b = -1
	return 0;
}

按位操作符 & | ^

& 按位与

c = a & b ,将a与b的补码每一位进行比照,如果a和b所对应位都是1则是1,否则是0,传给c的对应二进制位。

int main()
{
	int a = -6;
	int b = -2;
	int c = 0;
	c = a & b; // c的补码(8位) 11111010,转换为原码,对补码取反+1,即10000110(-6)
	printf("c = %d\n", c); //c = -6
	return 0;
}

| 按位或

c = a & b ,将a与b的补码每一位进行比照,如果a和b所对应位其中一个是1则是1,否则是0传给c的对应二进制位。

int main()
{
	int a = -6;
	int b = -2;
	int c = 0;
	c = a | b; // c的补码(8位) 11111110,转换为原码,对补码取反+1,即11111110(-2)
	printf("c = %d\n", c); //c = -2
	return 0;
}

^ 按位异

c = a ^ b ,将a与b的补码每一位进行比照,如果a和b所对应位不同则是1,相同是0,传给c的对应二进制位。

int main()
{
	int a = 7;
	int b = 13;
	int c = 0;
	c = a ^ b; 
	printf("c = %d\n", c); //c = 10
	return 0;
}

其中,^操作符有以下的性质
a^a  = 0  a异或自身得到的结果是0
a^0 = a   a异或0得到的是自身a
a^b^c = a^c^b 异或操作符支持交换律和结合,由此 如果 a^b^a = b  a^b^b = a

~ 按位反

~a,对a的补码取反,是1则是0,0则是1,,是单目操作符。对一个数的补码取反。

int main()
{
	int a = 10;
	printf("~a = %d", ~a); //~a = -11
	return 0;
}

移位操作符的代码实例

求对应值的补码(二进制)

右移实现

void RBinnary(int num)
{
	int i = 0;
	for (i = 31; i >=0; i--)
	{
		printf("%d", (num >> i) & (1));
	}
}

int main()
{
	int a = -2;
	RBinnary(a);
	return 0;
}

左移实现

void LBinnary(int num)
{
	int i = 0;
	for (i = 0; i <32; i++)
	{
		int is_one = (num << i) & (1 << 31);
		if (is_one)
			printf("1");
		else
			printf("0");
	}
}

int main()
{
	int a = -2;
	LBinnary(a);
	return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言学习 的相关文章

随机推荐

  • 使用IntelliJ IDEA查看类图

    使用IntelliJ IDEA查看类图 一 查看图形形式继承链 查看方式有如下两种 show Diagrams 新打开一个标签页 show Diagrams Popup 打开一个悬浮窗口 选择想查看已打开的类或者Project Tree中的
  • 趣味python编程之经典俄罗斯方块

    国庆期间闲不住 用python把经典俄罗斯方块实现了一遍 找到了些儿时的乐趣 因此突发奇想 正统编程之余也给自己找点儿乐趣 换个角度写程序 原计划是写篇完整的博文对程序算法和函数模块做个说明 但是在整理程序的时候发现自己给程序加的注释已经相
  • JUC基础【万字篇】

    JUC 1 什么是JUC JUC 指的是java util三个并发编程工具包 java util concurrent java util concurrent atomic java util concurrent locks 实现多线程
  • SpringBoot 三种拦截http请求方式Filter,interceptor和aop

    SpringBoot 三种拦截http请求方式Filter interceptor和aop 这三种拦截方式的拦截顺序是 filter gt Interceptor gt ControllerAdvice gt Aspect gt Contr
  • office word复制图片出错

    前言 今天在使用word文档时 发现在复制图片时 总是复制的不完整 Word中插入图片只显示一行的 图片缺失的部分感觉和文字交织在一起 估计原因是 之前图片复制在word中的标题的位置上了 解决 点击word上方的 正文 然后再复制图片 问
  • 【C++ primer】第一章 快速入门 读书笔记

    1 1 编写简单的c 程序 返回 0值表明程序程序成功执行完毕 非零返回值表明有错误出现 返回值类型必须和函数的返回类型相同 或者可以转换成函数的返回类型 1 1 1 编译与执行程序 1 2 初窥输入 输出 术语 流 试图说明字符是随着时间
  • Python 爬虫库以及库函数总结&&踩坑

    1 Re库的基本使用 Re库介绍 Re库是Python的标准库 主要用于字符串匹配 调用方式 import re 正则表达式的表示类型 raw string类型 原生字符串类型 re库采用raw string类型表示正则表达式 表示为 r
  • Qt文本的淡入淡出

    Qt文本的淡入淡出 对于写在Qlabel中的文本 想对其实现淡入和淡出的特效 需要用到QGraphicsOpacityEffect 并搭配计时器使用 示例如下 h文件 include
  • [虎符ctf2021]你会日志文件分析吗

    SQL盲注 拿到一份日志 毫无头绪 上网查wp得知为sql盲注 得再学 1 看时间和后门的长度 sleep 2 1 HTTP 1 1 200 377 如果正确会休眠两秒 那么就找到377长度的请求 Ctrl F sleep 2 1 HTTP
  • 独立服务器比较虚拟机有什么好处

    1 资源不足 采用虚拟主机服务的用户实际上很难确切地知道到底有多少客户正在同时分享现实服务器的资源 当与您的网站在同一台服务器上的某个 些 网站的访问量很大时 这台服务器的系统结构可能很容易就不堪重负 出现过载 从而大大影响其它网站系统的性
  • Qt 定时器实现循环

    概述 后台进程需要循环时第一时间想到的就是while 但是涉及界面交互时就不那么适用了 例如在Qt主线程中直接使用循环就会导致界面卡死 此时可以使用多线程来解决这个问题 但只是做一些简单的测试工具时 考虑线程大可不必 第二种方法就是在whi
  • c语言rtsp客户端拉流,如何基于C++解决RTSP取流报错问题

    使用g opencv demo cpp o test 会报以下错误 这是我的代码 include include include include include include include include pragma comment
  • Ubuntu 14.04 apt-get update失效解决

    当运行apt get update后出现如下错误时 E Some index files failed to download they have been ignored or old ones used instead 可以将目录下 v
  • centos升级g++7.3.0

    sudo yum install centos release scl sudo yum install devtoolset 7 scl enable devtoolset 7 bash
  • Dubbo分布式日志追踪

    很多互联网公司都用的dubbo分布式框架进行微服务的开发 一个大系统往往会被拆分成很多不同的子系统 并且子系统还会部署多台机器 当其中一个系统出问题了 查看日志十分麻烦 所以我们需要一个固定的流程ID和机器ip地址等来把所有的日志穿起来 当
  • 如何安装vcpk

    如何安装vcpk 要安装 3fd 库 首先你需要安装 vcpkg 包管理器 以下是安装 vcpkg 的步骤 打开一个命令行终端 如 Windows 的命令提示符或 PowerShell 或者 Linux Mac 的终端 克隆 vcpkg 存
  • [云原生专题-53]:Kubesphere云治理-操作-通过Kubesphere应用商店一键部署微服务应用-消息中间件RabbitMQ的安装与部署

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https blog csdn net HiWangWenBing article details 122933831 目录 前言 第1章
  • exportfs命令、NFS客户端问题、FTP介绍、使用vsftpd搭建ftp

    exportfs命令 参数说明如下 a 全部挂载 或卸载 etc exports文件内的设定 r 重新挂载 etc exports中的设置 此外同步更新 etc exports及 var lib nfs xtab中的内容 u 卸载某一目录
  • python面向对象编程 类与实例 继承与多态 isinstance

    class Student object def init self name gender self name name self gender gender def set gender self gender if gender ma
  • C语言学习

    目录 原码反码和补码 原码 true code 反码 complemental code 补码 ones complement code 溢出的处理 位运算符 移位操作符 lt lt gt gt lt lt 左移 gt gt 右移 按位操作