深入理解计算机系统(2.2)---布尔代数以及C语言上的位运算
布尔代数上的位运算
布尔代数是一个数学知识体系,它在0和1的二进制值上演化而来的。
我们不需要去彻底的了解这个知识体系,但是里面定义了几种二进制的运算,却是我们在平时的编程过程当中也会遇到的。这四种运算分别是或、与、非和异或。下图展示了在布尔代数的知识体系中,对这四种运算的定义。

从左至右依次是非、与、或以及异或。这个图阐述的是针对一位二进制的运算结果,我们可以将其扩大到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。LZ在此写了一个小程序,我们来简单的看下二者的区别。
#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);
}
从这个程序的结果可以很明显的看出!和~运算的区别,我们来直接看结果吧。

结果很明显,左边是!x以及!!x的结果,只有0和1,而右边则是~x和~~x的结果。这里可以很明显的看出逻辑非与位的非运算的区别。前者只有0和1,而后者则是对每一位二进制值取反。
除了结果上的区别之外,它们二者还有一个区别,就是逻辑运算倘若可以根据第一个表达式确定结果的话,那么将不会计算第二个表达式。举个简单的例子,假设有两个表达式a和b,对于a && b,倘若a为假,则不会计算b表达式的值。但是对于a & b则不同,无论a表达式的值为何,都要计算b表达式的值。
C语言的移位运算
移位运算分为两种,左移和右移。对于一个二进制数[aw,aw-1,...a1]来说,如果将它进行左移运算,则x << k = [aw-k,aw-k-1,...a1,0,...0]。此时相当于最高的那k位都被丢弃了,在最右端补了k个0。而对于x >> k来说,也就是右移运算,与左移是类似的,只不过为了照顾有符号数,有时候需要在左端补最高位而不是0。而对于补0的情况,则称为逻辑右移,补最高位的则称为算术右移。
也就是说,对于逻辑右移来说,x >> k = [0,...0,aw,aw-1,...ak+1],而对于算术右移来说,x >> k = [aw,...aw,aw,aw-1,...ak+1]。
本章小结
本章主要只是简单的介绍了下C语言中的位运算,下一章将会介绍一下整数的表示方式。
深入理解计算机系统(2.2)---布尔代数以及C语言上的位运算的更多相关文章
- 深入理解计算机系统(2.5)------C语言中的有符号数和无符号数以及扩展和截断数字
上一篇博客我们讲解了计算机中整数的表示,包括无符号编码和补码编码,以及它们之间的互相转换,个人觉得那是非常重要的知识要点.这篇博客我们将介绍C语言中的有符号数和无符号数以及扩展和截断数字. 1.C语言 ...
- 深入理解计算机系统(2.4)---C语言的有符号与无符号、二进制整数的扩展与截断
开篇请各位猿友允许LZ啰嗦几句,最近一直在写计算机系统原理这系列文章,也已经下定决心要把这本书的内容写完.主要目的其实是为了巩固LZ的理解,另外也想把这些内容分享给猿友们,毕竟LZ觉得这些内容对程序猿 ...
- 深入理解计算机系统(2.3)------布尔代数以及C语言运算符
本篇博客我们主要讲解计算机中的布尔代数以及C语言的几个运算符. 1.布尔代数 我们知道二进制值是计算机编码.存储和操作信息的核心,随着计算机的发展,围绕数值0和1的研究已经演化出了丰富的数学知识体系. ...
- 《深入理解计算机系统》【PDF】下载
<深入理解计算机系统>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382303 内容提要 本书主要介绍了计算机系统的基本概念,包 ...
- 深入理解计算机系统 (Randal E.Bryant / David O'Hallaron 著)
第1章 计算机系统漫游 (已看) 1.1 信息就是位+上下文 1.2 程序被其他程序翻译成不同的格式 1.3 了解编译系统如何工作是大有益处的 1.4 处理器读并解释存储在内存中的指令 1.4.1 系 ...
- 《深入理解计算机系统V2》学习指导
<深入理解计算机系统V2>学习指导 目录 图书简况 学习指导 第一章 计算机系统漫游 第二章 信息的表示和处理 第三章 程序的机器级表示 第四章 处理器体系结构 第五章 优化程序性能 第六 ...
- 深入理解计算机系统(4.1)---X86的孪生兄弟,Y86指令体系结构
引言 各位猿友们好,计算机系统系列很久没更新了,实在是抱歉之极.新的一年,为了给计算机系统系列添加一些新的元素,LZ将其更改为书的原名<深入理解计算机系统>.这本书非常厚,而且难度较高,L ...
- 深入理解计算机系统(1.2)---hello world的程序是如何运行的
在写本章的内容之前,LZ先做个小广告.其实也不算是什么广告,就是LZ为了和各位猿友交流方便,另外也确实有个别猿友留言或者在博客里发短消息给LZ要联系方式.因此LZ斗胆建立了一个有关<深入理解计算 ...
- 《深入理解计算机系统》 Chapter 7 读书笔记
<深入理解计算机系统>Chapter 7 读书笔记 链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(货被拷贝)到存储器并执行. 链接的时机 编译时,也就是 ...
随机推荐
- MySQL 5.6 主从复制如何处理——触发器,函数,存储过程,调度事件
截图来自MySQL5.6的pdf版文档. 说明: 1)基于语句的复制时,trigger会在slave上执行,所以slave上也需要有trigger的定义,不然会导致主从数据不一致的: 2)基于行的 ...
- PHP读取mssql,json数据中文乱码
PHP及网页使用UTF-8编码,数据库是sql server2008,使用默认编码(936,即GBK编码) 当读取数据库数据时,使用php自带的json_encode()返回到前端,结果中文不显示. ...
- InnoDB源码分析--缓冲池(三)
转载请附原文链接:http://www.cnblogs.com/wingsless/p/5582063.html 昨天写到了InnoDB缓冲池的预读:<InnoDB源码分析--缓冲池(二)> ...
- x01.os.14: 时间都去哪儿了
时间都去哪儿了 老帕的“花儿为什么这样红”,三分钟引起六次欢呼,却败给了张碧晨.试想一下,如果是人气更高的陈冰,即使唱得和张碧晨一模一样,可能仍然不敌老帕,为什么张碧晨就能取胜呢?有这么个笑话:一人弹 ...
- java 自动装箱自动拆箱
1.Java数据类型 在介绍Java的自动装箱和拆箱之前,我们先来了解一下Java的基本数据类型. 在Java中,数据类型可以分为两大种,Primitive Type(基本类型)和Reference ...
- hdu 3472 HS BDC(混合路的欧拉路径)
这题是混合路的欧拉路径问题. 1.判断图的连通性,若不连通,无解. 2.给无向边任意定向,计算每个结点入度和出度之差deg[i].deg[i]为奇数的结点个数只能是0个或2个,否则肯定无解. 3.(若 ...
- netfilter-在内核态操作网络数据包
一.概述 netfilter是自2.4内核的一个数据包过滤框架.可以过滤数据包,网络地址和端口转换 ...
- [译] OpenStack Liberty 版本中的53个新变化
一个新的秋季,一个新的OpenStack 版本.OpenStack 的第12个版本,Liberty,在10月15日如期交付,而且目前发行版本已经备好了.那么我们期望能从过去六个月时间的开发中获得些什么 ...
- 突然发现这周有点忙。。着玩-PHP进阶
hi 周二才,不过我突然意识到这周有点忙着玩的感觉,还是很期待的——今天下午去市里,晚上回来看电影,明晚聚餐吃火锅,后天下午拍短片,晚上可能要打球,周五,嗯,就到周五了.虽然这样下去连怎么写(bian ...
- 【温故而知新-Javascript】使用 Ajax(续)
1. 准备向服务器发送数据 Ajax 最常见的一大用途是向服务器发送数据.最典型的情况是从 客户端发送表单数据,即用户在form元素所含的各个 input 元素里输入的值.下面代码展示了一张简单的表单 ...