布尔代数以及C语言上的位运算

来源:互联网 发布:android libc 源码 编辑:程序博客网 时间:2024/03/28 17:22

布尔代数以及C语言上的位运算

布尔代数是一个数学知识体系,它在01的二进制上演化而来.

 

我们不需要去彻底了解这个知识体系,但是里面定义了集中二进制的运算,却是我们在平时的编程过程中也会遇到的.这四种运算分别是或,,,异或.下图展示了布尔代数的知识体系,对这四种运算的定义:

 

 

从左到右依次是非,,,异或.这个图阐述的是针对一位二进制的运算结果,我们可以将其扩大到N位二进制.比如两个二进制[aw,aw-1...a1]和[bw,bw-1...b1],它们的四种运算则是对两者每一个相对应的位上做相应的运算。

也就是说,倘若假设结果是[cw,cw-1...c1]的话,那么对于任意ci都满足ci = ai (|,&,^) bi,如果是对[aw,aw-1...a1]进行非运算的话,那么ci = ~ai。

 

C语言上的位运算

C语言中,也支持位运算,而他的计算方式就是布尔代数中的位运算.位运算我们最常使用的是掩码的方式.比如我们知道一个整数x,如果我们想取得这个整数得最后一个字节的整数值的话,就可以采用位运算.就像下面这样

#include <stdio.h>

 

int main(){

     unsigned int i = 0x12345678;

     unsigned int j = 0xFF;

     unsigned int k = i & j;

     printf("%X\n",k);

}

最终我们得到的结果是78,也就是整数i的最后一个字节的值,我们使用掩码0xFF以及与运算符过略掉整数i的高位的三个字节.

 

 

 

C语言的逻辑运算

C语言的逻辑运算有||,&&!,这比较容易与刚才的|,&~搞混.逻辑运算符比较特别,在这种运算的结果中认为所有非0的数值都是true,而为0的则为false.案例如下:

#include <stdio.h>

 

int main(){

      unsigned int x = 0x12345678;

      unsigned int i = !x;

      unsigned int j = ~x;

      unsigned int m = !!x;

      unsigned int n = ~~x;

      printf("%u %u\n",i,j);

      printf("%u %u\n",m,n);

}

从这个程序的结果可以很容易的看出!~运算的结果,输出如下:

0 3989547399

1 305419896

结果很明显,左边是!x以及!!x的结果,只有01,而右边的则是~x~~x的结果.这里可以很明显的看出逻辑非与位的非运算的区别.前置只有01,而后者则是针对每一位二进制取反.

 

除了结果上的区别之外,它们二者还有一个区别,就是逻辑运算倘若可以根据第一个表达式确定结果的话,那么将不会计算第二个表达式.撅个简单的例子,假设有两个表达式ab,对于a&&b,倘若aa,则不会计算b表达式的值.但是对于a&b则不痛,无论a表达式的值为何,都要计算b表达式的值.

 

 

 

 

 

C语言的移位运算

移位运算分为两种,左移(<<)和右移(>>).

举个例子吧,这个不好说

设无符号短整型变量a0111(对应二进制数为0000000001001001),
   则:a<<3 结果为01110(对应二进制数为0000001001001000)a的符号不变
     a>>4 结果为4(对应二进制数为0000000000000100)a的符号不变
  又如,设短整型变量a-4(对应二进制数为1111111111111100),


   则:a<<3 结果为-32(对应二进制数为1111111111100000)a的符号不变
     a>>4 结果为-1(对应二进制数为1111111111111111)a的符号不变

 

 

你明白吗?知道这些结果咋来的吗?

因为我个人感觉这一块比较重要,所以我要说明白:

左移运算符是用来将一个数的各二进制位左移若干位,移动的位数由右操作数指定(右操作数必须是非负值),其右边空出的位用0填补,高位左移溢出则舍弃该高位.

例如:a的二进制数左移2,右边空出的位补0,,左边溢出的位舍弃.a=5,二进制表示a=00001111,左移2位得到00111100.

你看看源代码:

#include <stdio.h>

void main()

{

int a=15;

printf("%d\n",a<<2);

}

左移1位相当于该数乘以2,左移2位相当于该数乘以2*2=4,15<<2=60,即乘了4.但是这个结论只适用于该数左移时被移除舍弃的高位不包含1的情况.

结社以一个字节(8)存一个整数,a为无符号整型变量,a=64,左移一位时溢出的是0,而左移2位时,溢出的高位中包含1.

 

 

右移运算符

右移运算符是用来将一个数的各二进制位右移若干位,移动的位数由右操作数指定(右操作数必须是非负

值),移到右端的低位被舍弃,对于无符号数,高位补0。对于有符号数,某些机器将对左边空出的部分

用符号位填补(即算术移位),而另一些机器则对左边空出的部分用0填补(即逻辑移位)。注

意:对无符号数,右移时左边高位移入0;对于有符号的值,如果原来符号位为0(该数为正),则左边也是移

0。如果符号位原来为1(即负数),则左边移入0还是1,要取决于所用的计算机系统。有的系统移入0,有的

系统移入1。移入0的称为逻辑移位”,即简单移位;移入1的称为算术移位。 
例: a的值是八进制数113755: 
   a:1001011111101101 (用二进制形式表示)
   a>>1: 0100101111110110 (逻辑右移时)
   a>>1: 1100101111110110 (算术右移时)
   在有些系统中,a>>1得八进制数045766,而在另一些系统上可能得到的是145766Turbo C和其他一些C

编译采用的是算术右移,即对有符号数右移时,如果符号位原来为1,左面移入高位的是1
源代码:
#include <stdio.h>
main()
{
 int a=0113755;
 printf("%d",a>>1);
}

 

 

 

在不明白自己看书吧.....

 

0 0
原创粉丝点击