C語言程序設(shè)計第11章--位運算課件_第1頁
C語言程序設(shè)計第11章--位運算課件_第2頁
C語言程序設(shè)計第11章--位運算課件_第3頁
C語言程序設(shè)計第11章--位運算課件_第4頁
C語言程序設(shè)計第11章--位運算課件_第5頁
已閱讀5頁,還剩47頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、 程序設(shè)計技術(shù)基礎(chǔ)第十一章 位 運 算11.1 數(shù)字系統(tǒng)、位和字節(jié)11.2 位運算符與位運算11.3 位運算應(yīng)用程序舉例11.4 位 段2022/7/18211.1 數(shù)字系統(tǒng)、位和字節(jié)11.1.1 數(shù)字系統(tǒng)數(shù)制也稱計數(shù)制,是用一組固定的符號和統(tǒng)一的規(guī)則來表示數(shù)值的方法。按進位的方法進行計數(shù),稱為進位計數(shù)制。如在日常生活中使用的十進制,在計算機中采用的二進制,以及八進制、十六進制等都是進位計數(shù)制。一種進位計數(shù)制包含一組數(shù)碼符號和兩個基本要素:基數(shù)和位權(quán)。2022/7/1831數(shù)碼數(shù)碼是指數(shù)制中表示基本數(shù)值大小的不同符號。例如十進制有10個數(shù)碼:0、1、2、3、4、5、6、7、8、9。二進制有2個

2、數(shù)碼:0、1。八進制有8個數(shù)碼:0、1、2、3、4、5、6、7。十六進制有16個數(shù)碼:09和A、B、C、D、E、F。2022/7/1842基數(shù)基數(shù)是指數(shù)制所使用數(shù)碼的個數(shù)。例如,二進制的基數(shù)為2;十進制的基數(shù)為10。在運算中,當(dāng)某一位上達到或超過基數(shù)大小時,就會向前進一。如十進制滿十進一,二進制滿二進一,十六進制則滿十六進一。2022/7/1853位權(quán)位權(quán)是指數(shù)制中每一固定位置對應(yīng)的單位值。一個數(shù)據(jù)在某個位置上的值等于該數(shù)字與這個位置上的因子的乘積,而該因子的值是由所在位置相對于小數(shù)點的距離來確定的,這個因子就是位權(quán),即各進位制中位權(quán)的值是基數(shù)的若干次冪。例如:十進制的123:1的位權(quán)是102

3、=100,2的位權(quán)是101=10,3的位權(quán)是100=1;二進制中的 1101 ,第一個1的位權(quán)是23=8,第二個1的位權(quán)是22=4,0的位權(quán)是21=2,第三個1的位權(quán)是20=1。2022/7/186任意的R進制數(shù)N按位權(quán)展開形式如下:其中:ri為計數(shù)制中任一個數(shù)碼,R為基數(shù)。為了區(qū)分不同數(shù)制的數(shù)據(jù),可以用括號加基數(shù)下標(biāo)表示數(shù)據(jù)所屬的數(shù)制。如:十進制數(shù)309.84的位權(quán)展開式為:(309.84)10=3102+0101+9100+810-1+410-2二進制數(shù)11011.01 的位權(quán)展開式為:(11011.01)2=124+123+121+120+12-22022/7/18711.1.2 位和字

4、節(jié)在計算機中,表示信息的單位有位、字節(jié)、兆、吉等,它們是表示信息量大小的基本概念。1位(bit)位,音譯為“比特”,是計算機內(nèi)構(gòu)成信息的最小數(shù)據(jù)單位,即一個1或0。一般用小寫字母“b”表示。一位二進制可表示21=2個信息,如:是或否,有或無,真與假等。2022/7/1882字節(jié)(Byte)字節(jié)是計算機數(shù)據(jù)存儲和處理信息的基本數(shù)據(jù)單位。簡記為“B”規(guī)定1個字節(jié)為8位,即8個二進制位是一個字節(jié)。 1B=8b。2022/7/189存儲器的存儲容量除了以位、字節(jié)為單位來度量外,還需要一些更大的單位,有KB、MB、GB、TB等度量單位:1KB=210B=1024B (K代表“千”)1MB=220B=21

5、0210B=10241024B (M代表“兆”)1GB=230B=210210210B=102410241024B (G代表“吉”)1TB=240B=210210210210B=1024102410241024B (T代表“太”)2022/7/181011.2 位運算符與位運算C語言的位運算可以分為位邏輯運算與位移位運算,共計6種基本位運算符:注:(1)位運算符中,除是單目運算符外,其余均為雙目運算符; (2)運算量只能是整型或字符型的數(shù)據(jù),不能為實型數(shù)據(jù)2022/7/1811運算符含義運算符含義&按位與|按位或按位異或按位取反右移11.2.1 位邏輯運算符與運算1“按位與”運算(&) “按位

6、與”是指參加運算的兩個數(shù)據(jù),按對應(yīng)的二進制位分別進行“邏輯與”運算。如果兩個相應(yīng)的二進制位都為1,則該位的運行結(jié)果為1(真);否則為0(假)。0&0=0; 0&1=0; 1&0=0; 1&1=12022/7/1812例如:13&10=? 00001101 (=13) (&) 00001010 (=10) 00001000 (=8)2022/7/1813 “按位與”運算有一些特殊的用途:2022/7/1814(1)清零:若想將某個二進制數(shù)的指定位清零,可將待清零位與0進行“按位與”運算,其余位與1進行“按位與”運算;若想將該數(shù)各位都清零,可使其與零進行“按位與”運算?!纠?1-6】將字符變量ch

7、所占的字節(jié)單元清零。 【例11-6】將字符變量ch所占的字節(jié)單元清零。程序如下:#includeint main( ) char ch=67; printf(ch=%d n,ch); ch=ch&0; printf(ch&0后ch=%d n,ch ); return 0;2022/7/1815程序運行結(jié)果為:ch=67ch&0后ch=0(2)保留指定位:若想保留某個二進制數(shù)中的指定位??蓪⒅付ㄎ慌c1進行“按位與”運算,其余位與0進行“按位與”運算即可實現(xiàn)。例如對一個十六位二進制整數(shù)a,若想要將其高八位清0,而保留其低八位。則進行:a & 00000000 11111111 運算即可: 0000

8、0001 00110100 (a=308) (&) 00000000 11111111 (=255) 00000000 00110100 (=52)2022/7/18162“按位或”運算(|)按位或”是指參加運算的兩個數(shù)據(jù),按對應(yīng)的二進制位分別進行“邏輯或”運算。如果兩個相應(yīng)的二進制位都為0,則該位的運算結(jié)果為0(假);否則為1(真)。即:0|0=0; 0|1=1; 1|0=1; 1|1=1例如13|10的運算為:2022/7/1817 00001101 (=13) (|) 00001010 (=10) 00001111 (=15)“按位或”運算的一大用途是經(jīng)常用來對一個數(shù)據(jù)的某些位置1?!纠?/p>

9、11-7】將一個8位的二進制整數(shù)的低4位置1,高4位不變。2022/7/1818程序如下:#includeint main( )char x=67; printf(“x初值為%dn”,x); x=x|15; printf(“x|15運算后的值為%dn”,x); return 0;程序運行結(jié)果為:x初值為67x|15運算后的值為793“按位異或”運算()“按位異或”是指參加運算的兩個數(shù)據(jù),按對應(yīng)的二進制位分別進行“邏輯異或”運算。如果兩個相應(yīng)的二進制位為“異”(值不同),則該位的運算結(jié)果為1(真);否則運算結(jié)果為0(假)。即00=0; 01=1; 10=1; 11=0例如:1310的運算為:20

10、22/7/1819 00001101 (=13)() 00001010 (=10) 00000111 (=7) “按位異或”運算有以下用途:(1)保留原值:與0進行“按位異或”運算,可保留原值。即: a0=a。例如: 130的運算為: 00001101 (=13) () 00000000 結(jié)果為: 00001101 2022/7/1820(2)使特定位翻轉(zhuǎn):與1進行“按位異或”運算,可使操作數(shù)特定位進行翻轉(zhuǎn),即由0變1或者由1變0。2022/7/1821程序如下:#includeint main( )char x=l;printf(“l(fā)=%dn”,x);x=x15;printf(x15=%dn

11、,x);return 0;【例11-8】設(shè)字符x=l,將其二進制數(shù)的高4位保留原樣,低4位各位翻轉(zhuǎn)。 01101100 (=108)()0000 1111 (=15) 0110 0011 (=99)程序運行結(jié)果為:l=108x15=99(3)置零:每一個數(shù)與它自身進行“異或”運算,結(jié)果各位均為零。即:xx=0。2022/7/18224“按位取反”運算() 按位取反”運算符“”是唯一的一個單目位運算符,用來將一個二進制數(shù)的每一位取反,即將1(真)變0(假),將0(假)變1(真)。即0=1; 1=0按位取反”運算常用來生成與系統(tǒng)實現(xiàn)無關(guān)的常數(shù),以增加程序的可移植性。如要將變量x=103=(1100

12、111)2最低6位置成0,其余位不變。用“按位與”運算實現(xiàn),就需要考慮x在系統(tǒng)內(nèi)存放的位數(shù):如果x占2個字節(jié),則需要執(zhí)行:x=x&0 xffc0如果x占4個字節(jié),則需要執(zhí)行:x=x&0 xffffffc0但若果把表達式變?yōu)椋簒=x&0 x3f整數(shù)x占2個字節(jié)還是占4個字節(jié)都能實現(xiàn)要求,大大增強了程序的可移植性。2022/7/182311.2.2 位移位運算符與運算1“左移”運算()左移運算符“”是雙目運算符,左移運算的一般形式為:運算對象左移位數(shù)。左移的作用是將一個數(shù)的各二進制位依次左移若干位(由左移位數(shù)給出),左移時,右端(低位)補0,左端(高位)移出的部分舍去。2022/7/1824例如,

13、假設(shè)以一個字節(jié)存一個整數(shù),則無符號整型變量a=15,在執(zhí)行a=a2后,a的值變?yōu)?0。左移變化過程如下圖:可見,左移1位相當(dāng)于操作數(shù)乘以2,左移2位相當(dāng)于操作數(shù)乘以4,左移n位相當(dāng)于操作數(shù)乘以2n,此外,左移運算要比乘法快的多。但此結(jié)論只適用于該數(shù)左移時被溢出舍棄的高位中不包含1的情況。2022/7/18250000 11110001 11100011 1100左移一次左移一次例如:若變量a=65,即二進制數(shù)(01000001)2時,左移一位時溢出的是0,變?yōu)?10000010)2,即130。而左移2位時,溢出的高位中包含1,a的值變?yōu)?00000100)2,即4,則不符合上述結(jié)論?!纠?1-

14、9】輸入兩個數(shù)字符a和b,由a、b組合生成整數(shù)c(c用字符類型表示),并顯示出來。生成規(guī)則是:a的低4位作為c的高4位,b的低4位作為c的低4位。2022/7/1826#include int main() char a,b,c; while(1) printf(Please input a and b:n); scanf(%c,%c,&a,&b); if (a=0)&(b=0) break; a=a)右移運算符“”是雙目運算符,右移運算的一般形式為:運算對象右移位數(shù)右移的作用是將一個數(shù)的各二進制位依次右移若干位(由右移位數(shù)給出),右移時,右端(低位)移出的部分舍去,左端(高位)移入的二進制數(shù)

15、分兩種情況:對于無符號數(shù)和正整數(shù),高位補0;對于負整數(shù),有的系統(tǒng)高位補1,有的系統(tǒng)高位補0。補0的稱為“邏輯右移”,即簡單右移;補1的稱為“算術(shù)右移”。具體情況需要查閱相應(yīng)C編譯程序用戶手冊。2022/7/1828例如,占一個字節(jié)的無符號整型變量a=15,則a=a2后,a的值變?yōu)?(向下取整)。變化過程如圖11-2所示。可見,右移1位相當(dāng)于操作數(shù)除以2,右移2位相當(dāng)于除以4,右移n位相當(dāng)于操作數(shù)除以2n。但此結(jié)論只適用于該數(shù)為無符號數(shù)和正整數(shù)。2022/7/18290000 11110000 01110000 0011右移一次右移一次【例11-10】取一個無符號整數(shù)a(16位)從右端開始的47

16、位,重新構(gòu)成一個數(shù)。分析:設(shè)a=(00000000 11011001)2,其從右端開始的47位依次為1101,需要單獨提取出來構(gòu)成一個新數(shù)。2022/7/1830程序如下:#includeint main() unsigned a,b,c,d; printf(“Please input an octal number:”); scanf(%d,&a b=a4 c=(0=和=。它們和復(fù)合賦值運算符的運算規(guī)則相似,結(jié)合方向從右向左,即把左邊值與右邊值位運算之后賦值給左邊變量。例如:a&=0 x19等價于 a= a&0 x19 a=2等價于a=a22022/7/1831注意:不同類型的整數(shù)數(shù)據(jù)(即數(shù)

17、據(jù)長度不同)在進行混合類型的位運算時,系統(tǒng)會按右端對齊原則進行處理,按數(shù)據(jù)長度大的數(shù)據(jù)進行處理,將數(shù)據(jù)長度小的數(shù)據(jù)左端補0或1。例如char a與int b進行位運算時,按int 進行處理,char a轉(zhuǎn)化為整型數(shù)據(jù),并在左端補0。補位原則如下:(1)對于有符號數(shù)據(jù):如果a為正整數(shù),則左端補0,如果a 為負數(shù),則左端補1。(2) 對于無符號數(shù)據(jù):在左端補0。2022/7/1832 位運算符優(yōu)先級排列表2022/7/1833優(yōu)先級位運算符優(yōu)先級位運算符1425|3&6&=、=、|=、=11.3 位運算應(yīng)用程序舉例【例11-11】從鍵盤輸入一個整數(shù),判斷此數(shù)的奇偶性。分析:對一個二進制數(shù)而言,其最

18、低一位為0時,就是偶數(shù),否則為奇數(shù)。因此可利用“按位與”運算的保留指定位功能,將其二進制最后一位提取出來,加以判斷是0還是1。2022/7/1834#includeint main( ) int a; printf(Please input a number: ); scanf(%d,&a); if(a&0 x01)=0 printf(%d 是偶數(shù)!n ,a); else printf(%d是奇數(shù)! n,a); return 0;程序運行結(jié)果為:Please input a number: 1515是奇數(shù)!【例11-12】不用臨時變量,交換兩個字符變量的值。分析:這是一個經(jīng)典的問題,交換變量的

19、值,一般需要一個中間變量。然而利用“按位異或”運算中的位翻轉(zhuǎn)特性,可以在沒有中間變量的情況下實現(xiàn)整數(shù)間的互換。2022/7/1835#includeint main( )char a=12,b=10;printf(“原數(shù)為a=%d,b=%dn”,a,b);a=ab;b=ba;a=ab ;printf(“交換后為a=%d,b=%dn”,a,b);return 0;程序運行結(jié)果為:原數(shù)為a=12,b=10交換后為a=10,b=12【例11-13】從鍵盤上輸入一個十進制整數(shù),統(tǒng)計該整數(shù)所對應(yīng)的二進制數(shù)中1的個數(shù)(設(shè)整數(shù)占兩個字節(jié))。分析:統(tǒng)計一個整數(shù)m的二進制數(shù)中1的個數(shù),可以利用“按位與”運算判斷

20、最后一位是否為1,然后再利用 “右移”位運算,將m中的每一位依次移至最后一位進行上述判斷,直至結(jié)束。2022/7/1836#includeint main( ) int i,count,m;printf(Please input m:); scanf(%d,&m); count=0;for(i=0;i1; printf(Numbers of 1 in m is %dn,count);return 0;程序運行結(jié)果為:Please input m:15Numbers of 1 in m is 4【例11-14】循環(huán)移位。將十六進制數(shù)a進行循環(huán)右移,即a的二進制數(shù)的右端n位移到最左端n位。如:原數(shù)

21、a=(12345678)16,循環(huán)右移4位后為(81234567)16.分析:這里不能直接使用運算符,因為,運算符在左面添0或添1不確定。所以要用左移與右移組合使用以達到目的。設(shè)整數(shù)a=0 x12345678,內(nèi)存占4個字節(jié),循環(huán)右移n=4位(二進制位)。2022/7/1837#includeint main( )unsigned a,b,c; int n; printf(請輸入需要移動的數(shù)據(jù):a=);scanf(%x,&a); printf(請輸入需要移動的位數(shù):n=);scanf(%d,&n); b=an; c=c|b; printf(“%xn ”, c); return 0; 程序運行結(jié)

22、果為:請輸入需要移動的數(shù)據(jù):a=12345678請輸入需要移動的位數(shù):n=48123456711.4 位 段計算機所能表示的信息的最小單位是一個字節(jié),即8位。事實上在計算機用于過程控制、參數(shù)檢測或數(shù)據(jù)通信領(lǐng)域時,控制信息往往只占一個字節(jié)中的一個或幾個二進制位,例如,描述“真”或“假”時,通常用1表示“真”,0表示“假”, 只需1位即可,而不需要占用8位甚至更多。為了有效的利用存儲空間,提高效率,在C 語言中, 提供了一種特有的壓縮信息的數(shù)據(jù)結(jié)構(gòu)位段。 2022/7/1838位段(bit-field)是以位為單位來定義結(jié)構(gòu)體中的成員變量所占的存儲空間的長度。含有位段的結(jié)構(gòu)體稱為位段結(jié)構(gòu)。位段結(jié)構(gòu)

23、也是一種結(jié)構(gòu)體類型,與一般結(jié)構(gòu)體在形式與用法上是很相近的。只不過其中含有以位為單位定義存儲長度的整數(shù)類型位段成員。采用位段結(jié)構(gòu)既節(jié)省存儲空間,又可方便操作。2022/7/183911.4.1位段結(jié)構(gòu)類型1位段結(jié)構(gòu)類型定義C語言中的位段是以“位”為單位來定義結(jié)構(gòu)體中的成員長度的。其定義格式為:struct 位段結(jié)構(gòu)類型名 類型說明符1 位段名1:位段1占用位數(shù); /*最低位*/ 類型說明符2 位段名2:位段2占用位數(shù); /*次低位*/; 類型說明符n 位段名n:位段n占用位數(shù);2022/7/1840例如: struct packed_flagunsigned int f1 :1; unsigne

24、d int f2 :1; unsigned int f3 :1; unsigned int type :4;unsigned int index :9;2022/7/1841說明:該例中, 定義了一個位段結(jié)構(gòu) packed_flag。該結(jié)構(gòu)定義了五個位段成員,均為unsigned int 類型的。前三個位段依次叫做 f1、f2和f3,各占1 位;位段 type 占有 4 位;位段 index 占有 9 位。C 編譯器自動把上面的位段定義壓縮在一起,這樣結(jié)構(gòu)packed_flag類型總共使用了 16 位,即2個字節(jié)。位段定義注意事項(1)位段的類型只能是int或unsigned類型,不能是cha

25、r型或者浮點型;(2)在位段結(jié)構(gòu)中還可以定義無名位段。無名位段起位段之間的分隔作用。無名位段不能被訪問,但是會占據(jù)空間。例如:2022/7/1842struct packed1 unsigned f1:4;unsigned f2:1;unsigned :2; /*無名位段,起分隔作用*/unsigned f3:1; ;f1 f2 f3 4121f2后面的無名位段占據(jù)2位,但其空間不用(3)一個位段必須存儲在同一存儲單元,不能橫跨兩個存儲單元。如果一個單元空間不夠,則系統(tǒng)從下一個單元起存放該位段。(上述“存儲單元”可能是一個字節(jié),也可能是2個字節(jié),視不同的編譯系統(tǒng)而異)。假設(shè)現(xiàn)在的“存儲單元”是

26、2個字節(jié),則下列位段定義:2022/7/1843假設(shè)現(xiàn)在的“存儲單元”是2個字節(jié),則下列位段定義:struct packed2 unsigned f1:8;unsigned f2:4;unsigned f3:6;unsigned f4:2;一個存儲單元另一個存儲單元(4)長度為0的無名位段,可以強制其下一個位段到下一個存儲單元存放。例如:struct packed3unsigned f1:4; unsigned f2:2;Unsigned :0; unsigned f3:2; ;2022/7/1844一個存儲單元另一個存儲單元在這個位段定義中,f1、f2和f3共需要8位即可,但因為f2和f3之

27、間的0長度位段的存在,f3只能存入下一個存儲單元中。(5)在位段結(jié)構(gòu)體中,不一定必須是位段成員,也可以包含非位段成員。例如:struct packed4 unsigned f1:4;unsigned f2:4;unsigned f3:4;int n;/*非位段成員*/ data4;2022/7/184511.4.2位段結(jié)構(gòu)類型變量的定義與引用1定義位段結(jié)構(gòu)類型的變量位段結(jié)構(gòu)類型變量的定義方法和其它結(jié)構(gòu)類型變量定義方法一樣。(1)先聲明位段結(jié)構(gòu)類型再定義變量。例如利用上面已經(jīng)定義好的位段結(jié)構(gòu)類型packed_flag來定義變量data的語句為: struct packed_ flag data;

28、 位段結(jié)構(gòu)類型名 變量名;2022/7/1846(2)在聲明位段結(jié)構(gòu)類型的同時定義變量。其一般形式為:struct 位段結(jié)構(gòu)體名成員列表變量名列表;例如上述位段結(jié)構(gòu)類型變量data的定義語句也可寫成:2022/7/1847struct packed_flag unsigned int f1 :1; unsigned int f2 :1; unsigned int f3 :1; unsigned int type :4;unsigned int index :9;data; 2位段成員的引用定義位段結(jié)構(gòu)類型的變量后,就可以如引用一般結(jié)構(gòu)體成員一樣方便的引用位段成員:位段變量名.位段名例如由位段結(jié)構(gòu)packed_flag定義了位段變量data后,各位段就可以有如下引用:data.f1=0;data.f2=1; data.index=data.f1+10; 2022/7/18483位段引用時的注

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論