求两组整数的异或集c语言,C语言_位运算1

关于位运算相关内容分为两个大博文,分别为位运算1,即该博文;主要介绍二进制、位、字节的基本概念、进制转换问题,以及C的~ & | ^ 按位运算符及应用方法

由于篇幅限制,位运算2主要讲述左移和右移运算及编程练习以及字段运算

文章目录

0.引入

0.1 位运算的应用方向

0.2 二进制数、位和字节

0.2.1 二进制整数

0.2.2 有符号整数

0.2.3 二进制浮点数

1. 其它进制数

2. C按位运算符

2.1 按位逻辑运算符

2.1.1 二进制反码或按位取反:`~`

2.1.2 按位与:`&`

2.1.3 按位或:`|`

2.1.4 按位异或:`^`

2.2 按位运算符常见用法

2.2.1 用法一:掩码

2.2.2 用法二:打开位

2.2.3 用法三:关闭位

2.2.5 用法五:切换位

2.2.6 用法六:检查位的值

0.引入

0.1 位运算的应用方向

想硬件设备发送一两个字节来控制这些设备,其中每个位(bit)都有特定含义

与文件相关的操作系统信息经常被存储,通过使用特定位表明特定项

许多压缩和加密操作都是直接处理单独的位

通过应用可以看出,位运算主要应用在计算机软件与硬件交互的过程中使用,或者可以说是更底层的东西

C语言也是编写设备驱动程序和嵌入式开发的首选语言

0.2 二进制数、位和字节

二进制数(binary number):

以2为基底表示的数字被称为二进制数

例如二进制数1101可表示为:1x23+1x22+0x21+1x20

二进制系统可以把任意整数表示为0和1的组合,关于进制转换问题请参考博文进制转换相关内容

0.2.1 二进制整数

通常,1字节包含8位。C语言用字节(byte)表示存储系统字符集所需的大小

所以C字节可能是8位、9位、16位或其它值。但是,描述存储器芯片和数据传输率中所用的字节指的是8位字节。

本博文内容假设1字节=8位

通常用用术语 八位组(octet) 这个术语特指8位字节

计算机中从左往右给八位分别变好7~0。编号为7的成为高阶位(high-order bit) ,编号是0的位称为低阶位(low-oder bit) 每一位对应2的相应指数

3b601ca869e7304a51fafce94262dd76.png

如上图,1字节能表示的最大数字为11111111 其对应的十进制值为255

11111111=1x27+1x26+1x25+1x24+1x23+1x22+1x21+1x20=255

因此1字节可以存储0~255范围内的数字,总共256个值

对于unsigned char 中1字节存储范围为0~255,

对于signed char 中1字节表示范围为-128~+127

0.2.2 有符号整数

如何表示有符号整数取决于硬件,而不是C语言。一般地,C中用高阶位状态1表示负数,高阶位0表示正数

针对具体数的表示问题上及硬件关系,提出数的源码、反码、补码表示方法,具体请参见博文源码、反码、补码部分

0.2.3 二进制浮点数

浮点数分为两部分存储:二进制小数和二进制指数

1. 二进制小数表示方法

.101 的二进制表示为:1/21+0/22+1/23

.101 的十进制表示为:1/2+0/4+1/8=0.5+0+0.125

即,.101对应的十进制值为0.625

可以看出,二进制的表示法以2的指数进行计算,即二进制表示法只能精确的表示多个1/2的幂的和。

3/4和7/8可以精确的表示为二进制小数,但1/3和2/5却不能

2. 浮点数表示方法:

(此处没有理解)

bc90f04fa59d4fbda48c3f8cbcc7126f.jpg

1. 其它进制数

其它进制数包括八进制和十六进制数,相关内容参看博文:八进制、十六进制部分

2. C按位运算符

C中有两个操作位的工具。第一个工具为一套(6个)作用于位的按位运算符,第二个工具是字段(field) 数据形式,用于访问int中的位。该部分将介绍相关按位运算符。

按位运算符分为两类:一类是按位逻辑运算符,另一类是位移运算符

2.1 按位逻辑运算符

对于按位逻辑运算符请注意:

4个按位逻辑运算符都用于整型数据,包括char

按位(bitwise)运算是因为这些操作都是只针对每一位进行操作,而不影响它的左右两边的位。

不要把按位运算符于常规的逻辑运算符混肴,常规的逻辑运算符操作的是整个值

即,1字节8位,按位运算符对8位中的某一位操作,而常规逻辑运算符对整个字节操作

由于浮点型数据的表示上的特殊性,所以按位运算只在整型数据上应用

2.1.1 二进制反码或按位取反:~

一元运算符~将1变成0,0变成1

例如:

原始值10011010

进行取反操作:~(10011010)

结果值为:01100101

值得注意的是:

~不会改变原始值,但是该运算符创造了一个可以使用或赋值的新的值。

如:

int val=154;// val=10011010

int newVal=0;

newVal=~val;// ~(10011010)

printf("val=%d\t,newVal=%d\n",val,newVal);

5cb022864be648edade2ba60e4d7782c.jpg

2.1.2 按位与:&

二元运算符&通过逐位比较两个运算对象,生成一个新值。

对于每个位,只有两个运算对象中相应的值都为1时,结果才为1(从真假方面看,只有当两个位都为真时,结果才为真)。

如:

int valA=147;// valA=10010011

int valB=61;//valB=00111101

int newVal=0;

newVal=valA&valB;// newVal=00010001

printf("valA=%d\n,valB=%d\n,newVal=%d\n",valA,valB,newVal);

b919f8bc46414eb9a2a091dc661fdd0f.jpg

&=按位与运算符和赋值结合运算符,针对上面代码,可以写成如下形式

int valA = 147;// valA=10010011

valA &= 61;// ValA=00010001

printf("valA=%d\n",valA);

b6fe65846b836c9a68d32629579e86a4.png

2.1.3 按位或:|

二元运算符| 通过逐位比较两个运算对象,生成一个新值。

对于每个位,如果两个运算对象中相应的位为1,结果就为1(从真假方面看,如果两个运算对象中相应的一个位为真或者两个位都为真,那么结果为真)

如:

int valA=163;//valA=10010011

int valB=61;//valB=00111101

int newVal=0;

newVal=valA|valB;//newVal=191

printf("valA=%d\nvalB=%d\nnewVal=%d\n",valA,valB,newVal);

30ffd2b6994267b8dec221fd07d61697.png

针对|=有如下书写

int val=163;

val |= 61; ====等价于 val= val|61;

此时val的值为191

2.1.4 按位异或:^

二元运算符^逐位比较两个运算对象。

对于每个位,如果两个运算对象中相应的位一个为1(但不是两个为1),结果为1(从真假方面看,如果两个运算对象中相应的一个位为真且不是两个位同为1,那么结果为真)

如:

int valA=147;//valA=10010011

int valB=61;//valB=00111101

int newVal=valA^valB;

printf("valA=%d\nvalB=%d\nnewVal=%d",valA,valB,newVal);

151ec92b3930de9ec57c227f12e813b5.png

同样有^=运算符

int val=147;

val ^= 61; ======等价于 val= val^61

val=174

2.2 按位运算符常见用法

2.2.1 用法一:掩码

按位与&运算符常用于掩码(mask)。

掩码指的是一些设置为开(1)或关(0)的位组合。

掩码的使用过程

设定义符号常量MASK=2(二进制形式为00000010)

则语句:

int flages=150;//flages=10010110

int MASK=2;//MASK=00000010

flages &= MASK;

printf("flages=%d\n",flages);

65b69dd796474918bef2baef39afe6b0.jpg

表示掩码的使用,其作用过程如下

0e2eb6a22e1c9d8601a0f7741cd52737.png

2.2.2 用法二:打开位

有时,需要打开一个值中的特定位,同时保持其它位不变

例如,向一台IBM PC 通过向端口发送值来控制硬件;

例如,为了打开内置扬声器,必须打开1号位,同时保持其他位不变。这种情况可以使用按位或运算符

按位或|运算符常用于位的打开

例如:

int flages=31;//flages=00001111

int MASK=182;//MASK=10110110

flages |= MASK;

printf("flages=%d\n",flages);

7fb9e2f0197ea400448109a14656645a.png

2.2.3 用法三:关闭位

将某个位值设为0,通常需要&运算符

如:

int MASK=182;//MASK=10110110

int flags=15;//falgs=00001111

flags &= ~MASK;

printf("flags=%d",flags);

05f2aa5dd86b4687973c76b5ee9f9493.jpg

此操作关闭flags的第1 2 号位

2.2.5 用法五:切换位

切换位值得是打开已关闭的位或者关闭已打开的位

通常使用按位异或^运算符

如:

int flags=15;//flags=00001111

int MASK=182;//MASK=10110110

flags ^= MASK;

printf("flags=%d\n",flags);

f910668feeb3cde9cfc4ae309dab25f4.png

2.2.6 用法六:检查位的值

有时需要检查某位的值是否被设定为期望值

比如为比较flags中1号位的值是否为1

通常的做法为:

int MASK=2;//MASK=00000010

int flags=54;//flags=00110110

if((flags&MASK) == MASK)

{

puts("number 2 has been set as 1");

}

else

{

puts("number 2 set error");

}

2db2f5a252b306c279a852578a96627d.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值