C语言程序设计 第十二章 位运算.

Slides:



Advertisements
Similar presentations
While 迴圈 - 不知重複執行次數
Advertisements

首页 全国高等学校招生考试统一考试 监考员培训 广州市招生考试委员会办公室.
說 劍 《莊子‧雜篇》─ 第 一 組 賴泊錞 謝孟儒 張維真 羅苡芸
人口增长.
普通高等学校 本科教学工作水平评估方案.
成才之路 · 语文 人教版 • 中国古代诗歌散文欣赏 路漫漫其修远兮 吾将上下而求索.
第二章 复式记账原理*** 主要内容、重点难点: 1.会计要素与会计等式*** 2.会计科目与账户*** 3. 借贷记账法***
第一章 会计法律制度 补充要点.
二、个性教育.
江苏省2008年普通高校 招生录取办法 常熟理工学院学生处
1、分别用双手在本上写下自己的名字 2、双手交叉
神奇的宇宙 我们的太阳系 宇宙中天体有哪些类型? 刊号:CN77-87 编辑: 施雅苑 今日一叠4版 第1期 认识宇宙 16岁的哈勃
2007年11月考试相关工作安排 各考试点、培训中心和广大应考人员:
第一单元 人在社会中生活 综合探究一 从地图上获取信息 第1课时 带着地图定向越野间.
分式的乘除(1) 周良中学 贾文荣.
第四章 制造业企业 主要经济业务核算.
第二部分 人文地理 第一单元 人口与城市 第5课 城市化过程和特点. 第二部分 人文地理 第一单元 人口与城市 第5课 城市化过程和特点.
《思想品德》七年级下册 教材、教法与评价的交流 金 利 2006年1月10日.
财经法规与会计职业道德 (3) 四川财经职业学院.
平行线的性质 (第一课时) 说课者:邓燕锋 大亚湾区第二中学.
必备职业素养 主讲:程华.
江苏省2009年普通高校 招生录取办法 江苏省教育考试院
第十三章 收入和利润.
第4章 选择结构程序设计 在现实生活中,需要进行判断和选择的情况是很多的 如果你在家,我去拜访你 如果考试不及格,要补考
高级语言程序设计 主讲人:陈玉华.
循环结构又称为重复结构:用来处理需要重复处理的问题,它是程序中一种很重要的结构。
選擇排序法 通訊一甲 B 楊穎穆.
If … else 選擇結構 P27.
第5章 堆疊(Stacks) 5-1 堆疊的基礎 5-2 堆疊的表示法 5-3 堆疊的應用 - 運算式的計算與轉換
第二章 基本元素、类型和概念 七、输出函数printf 八、输入格式转换函数scanf.
第13章 结构体的应用 13.1 了解由用户构造的数据类型 13.2 结构体类型说明及结构体变量 13.3 结构体数组
第三节 整数类型.
第三章 数据类型、运算符与表达式.
2.1 C语言的数据类型 2.2 常量与变量 2.3 变量赋初值 2.4 各类数值型数据间的混合运算 2.5 C语言的运算符和表达式
第4章 顺序程序设计.
Struct結構 迴圈
目录 9.1 结构体类型 9.2 共用体类型 9.3 枚举类型 9.4 类型声明符typedef 1.
C语言概述 第一章.
第1讲 C语言基础 要求: (1) C程序的组成 (2) C语言的标识符是如何定义的。 (3) C语言有哪些基本数据类型?各种基本数
Main() { Dfas Asdfasf fasdfa } #include <stdio.h> void main( ) {
第11章 位运算 为了节省内存空间,在系统软件中常将多个标志状态简单地组合在一起,存储到一个字节(或字)中。C语言是为研制系统软件而设计的,所以她提供了实现将标志状态从标志字节中分离出来的位运算功能。 所谓位运算是指,按二进制位进行的运算。 11.1 数值在计算机中的表示 11.2.
第8章 位运算 本章导读 本章主要知识点 《 C语言程序设计》 (Visual C++ 6.0环境)
C语言的特点 1. C程序由许多函数组成 2. C程序必须有且只有一个主函数main( ) 3. 函数用“{”和“}”表示起点和终点
浙江长征职业技术学院—计算机与信息技术系—相方莉制作
指標
C语言程序设计 李祥 QQ:
C程序设计.
基础会计.
大綱:整數的加法 整數的減法 蘇奕君 台灣數位學習科技股份有限公司
第3章 数据类型、运算符与表达式.
项目1 C程序设计起步 学习目标: 通过该项目你可以知道: C语言的用途。 C语言的基本符号和关键字。 C语言程序的结构及特点。
第2章 数据类型、运算符与表达式 本章要点: 基本数据类型 常量和变量 算术运算符和算术表达式 关系运算符和关系表达式
第二章 类型、对象、运算符和表达式.
第2章 数据类型与表达式 学习目的与要求: 掌握C 语言的基本数据类型及使用方法 掌握C程序中常用的运算符和表达式 了解数据类型的转换.
5.2.2平行线的判定.
第二章 基本数据类型 ——数据的表示.
第四章 基本平面图形 线段、射线、直线.
C程序设计.
第八节 算术运算符和算术表达式.
第五章 逻辑运算和判断选取控制 §5.1 关系运算符和关系表达式
第十二章 位运算.
中级会计实务 ——第一章 总论 主讲:孙文静
第8章位运算 教学目的与要求: 1.熟练掌握六种位运算符及其使用方法 2.了解位段的使用方法.
目录 12.1 位运算符 12.2 位域(位段) 1.
第二章 数据类型、运算符和表达式 §2.1 数据与数据类型 §2.2 常量、变量和标准函数 §2.3 基本运算符及其表达式 目 录 上一章
C/C++基礎程式設計班 C語言入門、變數、基本處理與輸入輸出 講師:林業峻 CSIE, NTU 3/7, 2015.
C/C++基礎程式設計班 陣列 講師:林業峻 CSIE, NTU 3/14, 2015.
第三章 流程控制 程序的运行流程 选择结构语句 循环结构语句 主讲:李祥 时间:2015年10月.
C语言基础学习 从外行到入门.
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
Presentation transcript:

C语言程序设计 第十二章 位运算

主要内容 12.1 位运算的概念 12.2 位运算 12.3 位运算举例 12.4 位段

12.1 位运算的概念 C语言是为描述系统而设计的,既具有高级语言的特点,又具有低级语言的功能,因而具有广泛的用途和很强的生命力。 在计算机用于检测和控制等诸多领域中要用到位运算的知识,因此读者应当学习和掌握本章的内容。 所谓位运算是指进行二进制位运算。例如,将一个存储单元中的各二进位左移或右移一位,两个数按位相加等。本章讲述C语言位运算的功能。

12.1 位运算的概念 计算机内数据的表示方法 计算机内存储器由许多称为字节的单元组成的,每个字节由8个二进制位(8bit)构成,每位的取值为0或1。最右端的位称为“最低位”,编号为0;最左端的位称为“最高位”,而且按从最低位到最高位顺序,依次编号。下图是一个字节数据和它各二进制位的编号。 计算机中数是用二进制来表示的,数的符号也是用二进制表示的。一般用最高位作为符号位,0表示正数,用1表示负数。 位号 7 6 5 4 3 2 1 各位数据 一个字节数据和它各位编号

12.1 位运算的概念 补码 正数表示形式:符号位为0,其余部分表示数的绝对值。例如,+9的补码是00001001

12.1 位运算的概念 负数表示形式: -9的绝对值按位取反后加1,符号位以1表示负数。由于计算机的字长不同,为方便描述,因此约定用一个字节表示一个整数。见下图:

12.1 位运算的概念 位运算及其运算符 所谓位运算是指,按二进制位进行的运算,即从具有0或1的运算对象出发,计算得出具有0或1的运算结果。C语言的位运算又分为按位操作和移位操作,位操作包括按位与、或、异或和求反运算;移位操作包括左移和右移操作

12.1 位运算的概念 说明 位运算的优先级:由高到低的顺序是:~ → << 、>> → & → | → ^; 位运算的运算对象只能是整型(int)或字符型(char)的数据; 位运算是对运算量的每一个二进制位分别进行;

12.2 位运算 按位与运算(&) 参加运算的两个数据,按二进位进行“与”运算。如果两个相应的二进位都为1,则该位的结果值为1,否则为0。即 0&0=0;0&1=0;1&0=0;1&1=1; 例如: 3&5 并不等于8,应该是按位与。 3 = 0 0 0 0 0 0 1 1 & 5 = 0 0 0 0 0 1 0 1 1 = 0 0 0 0 0 0 0 1 因此,3&5的值得1。如果参加&运算的是负数(如-3 & -5),则以补码形式表示为二进制数,然后按位进行“与”运算。

12.2 位运算 按位与的实际用途 将一个数的某位清零 如果想将某个数的某个比特清零,只要另找一个数,让对应的该比特置0,然后使两数进行按位与&运算,即可达到将此数的特定比特清零的目的。 如:有数为00101011,想让该数从右数的第4比特变成0,其他位保持不变。我们另找一个数,该数从右数的第4比特设它为0,其他位全为1:11110111,将两个数进行&运算: 0 0 1 0 1 0 1 1 & 1 1 1 1 0 1 1 1 0 0 1 0 0 0 1 1

12.2 位运算 取一个数中某些指定位 如有一个两个字节整数 a=(16a1)16,想取出其中的低字节。我们构造一个数b,它的高字节全为0,低字节全为1,即b=(00ff)16=(255)10,只需将a与b按位与即可: a = (16a1)16 = (0001011010100001)2 & b = (00ff )16 = (0000000011111111)2 (00a1)16 = (0000000010100001)2

12.2 位运算 按位或运算(|) 两个相应的二进位中只要有一个为1,该位的结果值为1。即0|0=0;   0|1=1; 1|0=1; 1|1=1。 例如: (060)8 | (017)8 , 将八进制数60与八进制数17进行按位或运算: (060)8 = (0 0 1 1 0 0 0 0)2 | (017)8 = (0 0 0 0 1 1 1 1)2  (077)8 = (0 0 1 1 1 1 1 1)2 按位或常用来对一个数据的某些位定值为1。如:a是一个整数(16位),有表达式a |0377,0377为8进制数。则低8位全置为1。高8位保留原样。

12.2 位运算 异或运算(∧) 异或运算符∧也称XOR运算符。它的规则是若参加运算的两个二进位相同,则结果为0;相异则为1(真): 0∧0=0; 0∧1=1; 1∧0=1; 1∧1=0; 如: 00111001 (十进制数57,八进制数071) ∧ 00101010 (十进制数42,八进制数052) 00010011 (十进制数19,八进制数023) 即071∧052,结果为023(八进制数)。

12.2 位运算 异或运算应用 使特定位翻转:假设有01111010,想使其低4位翻转,即1变为0,0变为1。可以将它与00001111进行∧运算,即 0 1 1 1 1 0 1 0 ∧ 0 0 0 0 1 1 1 1 0 1 1 1 0 1 0 1 要使哪几位翻转就将与其进行∧运算的该几位置为1即可。 与0相∧,保留原值。如012∧00=012 0 0 0 0 1 0 1 0 ∧ 0 0 0 0 0 0 0 0 因为原数中的1与0进行∧运算得1,0∧0得0,故保留原数。

12.2 位运算 交换两个值,不用临时变量:假如a=3,b=4。想将a和b的值互换,可以按以下三个步骤实现: a = a∧b; b = b∧a; 我们用下面的竖式来说明: a = 0 1 1 ∧ b = 1 0 0 a = 1 1 1 (a∧b的结果,a已变成7) b = 0 1 1 (b∧a的结果,b已变成3) ∧ a = 1 1 1 a = 1 0 0 (a∧b的结果,a变成4)

12.2 位运算 “取反”运算(~) 按位取反~是一个单目运算符。例如: (~) 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 (~) 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 1 1 1 1 1 1 1 1 1 1 0 1 0 1 0 取反应用 若一个16位整数a,想使最低一位为0,可以将a 与二进制数1111111111111110 ( 0177776)8 进行按位与: 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 1 & 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 但若将此程序移植到32位计算机上,由于整数用4个字节表示,想将最后一位变成0就不能用a&0177776了,应改用a & 037777777776。这个算法的移植性很差,可以改用a=a&~1:

12.2 位运算 因为在以2个字节存一个整数时,1的二进制形式为0000000000000001,~1是1111111111111110。以4个字节存储一个整数时,~1是1111111111111111111111111111110。 ~运算符的优先级别比算术运算符、关系运算符、逻辑运算符和其他位运算符都高。例如:~a&b,先进行~a运算,然后进行&运算。

12.2 位运算 左移运算(<<) 用来将一个数的各二进位全部左移若干位,右边低位补0 。 例如:若a=15, a=a<<2,即二进制数00001111,左移2位得00111100,即十进制数60。高位左移后溢出,舍弃不用。 左移1位相当于该数乘以2,左移2位相当于该数乘以22=4。上面举的例子15<<2 = 60,即乘了4。但此结论只适用于该数左移时被溢出舍弃的高位中不包含1的情况。 左移比乘法运算快得多,有些C编译程序自动将乘2的运算用左移一位来实现,将乘2n的幂运算处理为左移n位。

12.2 位运算 右移运算符(>>) a>>2表示将a的各二进位右移2位。移出右端的低位被舍弃,对无符号数,高位补0。如a=017时:a为 00001111,a>>2为 00000011|11 。 右移一位相当于除以2,右移n位相当于除以2n。右移需要注意符号位。对无符号数,右移时左边高位移入0。对于有符号的值,如果原来符号位为0(该数为正),则左边也是移入0,如同上例表示的那样。如果符号位原来为1(即负数),则左边移入0还是1,要取决于所用的计算机系统。有的系统移入0,有的移入1。移入0的称为“逻辑右移”,即简单右移。移入1的称为“算术右移”。例如,a的值为八进制数113755: a: 1001011111101101 a>>1: 0100101111110110 (逻辑右移时) a>>1: 1100101111110110 (算术右移时)

12.2 位运算 位运算赋值运算符 位运算符与赋值运算符可以组成复合赋值运算符如:&=, |=, >>=, <<=, ∧=。 例如: a & = b 相当于 a = a & b a << =2 相当于 a = a << 2

12.2 位运算 不同长度的数据进行位运算 如果两个数据长度不同(例如long型和int型)进行位运算时(如a & b, a为long型,b为int型),系统会将二者按右端对齐。如果b为正数,则左侧16位补满0。若b为负数,左端应补满1。如果b为无符号整数型,则左侧添满0。

12.3 位运算举例 例1:将16进制数按二进制输出 #include <stdio.h> void main() { int i,a; printf(“请输入一个十六进制数:"); scanf("%x", &a); printf(“其二进制表示为:"); for (i=15;i>=0;i- -) printf(“%1d”, a&1<<i?1:0); //注意优先级,先移位<<,结果再与a按位与 printf("\n"); } 运行结果: 请输入一个十六进制数:40 其二进制表示为:0000000001000000

12.3 位运算举例 例 2:取一个整数a从右端开始的4~7位。 分析:可以这样考虑: 先使a右移4位。下图a是未右移时的情况,下图b是右移4位后的情况。目的是使要取出的那几位移到最右端。 右移到右端可以用下面方法实现:a >> 4

12.3 位运算举例 设置一个低4位全为1,其余全为0的数。可用下面方法实现: ~ ( ~ 0 << 4 ) 设置一个低4位全为1,其余全为0的数。可用下面方法实现: ~ ( ~ 0 << 4 ) ~0的全部二进制为全1,左移4位,这样右端低4位为0。见下面所示: 0: 0000…000000 ~0: 1111…111111 ~0<<4: 1111…110000 ~(~0<<4): 0000…001111

12.3 位运算举例 将上面二数进行&运算。即:(a >> 4) & ~ ( ~ 0 << 4 ) 根据上一节介绍的方法,与低4位为1的数进行&运算,就能将这4位保留下来。程序如下: #include "stdio.h" void main( ) { unsigned a,b,c,d; scanf("%d",&a); b=a>>4; c=~(~0<<4); d=b&c; printf(“输入数 = %d\n该数右端开始的4~7位数 = %d\n",a,d); } 运行结果: 输入数 = 217 该数右端开始的4~7位数 = 13

12.3 位运算举例 可以任意指定从右面第m位开始向左取n位。只需将程序中的“b=a>>4”改成“b=a>>(m-n+1)”以及将“c=~(~0<<4)”改成“c=~(~0<<n)”即可。

12.4 位段 在计算机过程控制、参数检测、或数据通信领域中,大部分控制信息往往只需用一个或几个二进制位表示即可,若存储一个这样的信息仍然以字节为单位,必然造成内存空间的浪费。为节省存储空间,我们自然想到可以将多个这样的信息放在同一个字节中表示,为此,C语言引入了位段类型。

12.4 位段 位段的概念与定义 所谓位段类型,是一种特殊的结构类型,其所有成员均以二进制位为单位定义长度,并称成员为位段,或称位域。位段类型的定义与结构体类型的定义类似,只不过定义成员的宽度以二进制位为单位。 人为地将一个int型变量data分为几个部分,其中a、b、c、d分别占2位、6位、4位和4位,按位段类型可定义如下:

12.4 位段 struct packed_data { unsigned a:2; unsigned b:6; unsigned c:4; unsigned d:4; } struct packed_data data;

12.4 位段 以上代码定义了位段类型packed_data,它由四个段域组成,其中第0~1位为a,第2~7位b,第8~11位为c,第12~15位为d,共占用两个字节的存储空间,可见,位段类型数据大大节省了存储空间。对位段中的数据进行引用和访问,也类型结构类型,如: data.a = 2; data.b = 25; data.c = 15; 引用时,要注意位段允许的最大范围,如data.c的宽度为4,则它的数据范围为0~15(二进制数的0000~1111)。

12.4 位段 关于位段的定义和引用的几点说明 位段成员的类型必须是unsigned或int类型,可以用%d、%u、%0和%x等格式字符,以整数形式输出位段; 位段赋值时要注意取值范围,通常,长度为n的位段,其取值范围为0~(2n-1); 一个位段必须存储在同一个存储单元,不能跨两个存储单元。如果第一个存储单元空间不能容纳下一个位段,则该空间不用,而从下一个单元起存放该位段。 可以定义无名位段,表示相应空间不用,或定义长度为0的无名位段,表示下一个位段从下一个存储单元开始存放。如:

12.4 位段 struct packed_data { unsigned a:2; unsigned b:4; unsigned :0; /* a、b存储在同一个单元,c、d另存在一个单元 */ unsigned c:3; unsigned :3; /* 这三位空间不用 */ unsigned d:2; } data;

12.4 位段 若data是以上定义的位段类型变量,并有以下引用: data.a=2; data.b=11; data.c=3;data.d=1 则变量data的值如下图所示,其中c从下一字节开始存放,c和d之间有两个二进制位是暂时不用的。