C語言程序設(shè)計基礎(chǔ)(第二版)課件:編譯預(yù)處理與位運(yùn)算-C語言的附加功能_第1頁
C語言程序設(shè)計基礎(chǔ)(第二版)課件:編譯預(yù)處理與位運(yùn)算-C語言的附加功能_第2頁
C語言程序設(shè)計基礎(chǔ)(第二版)課件:編譯預(yù)處理與位運(yùn)算-C語言的附加功能_第3頁
C語言程序設(shè)計基礎(chǔ)(第二版)課件:編譯預(yù)處理與位運(yùn)算-C語言的附加功能_第4頁
C語言程序設(shè)計基礎(chǔ)(第二版)課件:編譯預(yù)處理與位運(yùn)算-C語言的附加功能_第5頁
已閱讀5頁,還剩46頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

編譯預(yù)處理與位運(yùn)算

——C語言的附加功能10.1編譯預(yù)處理10.2位運(yùn)算實(shí)操訓(xùn)練課外練習(xí)

10.1編譯預(yù)處理

如何使用C語言系統(tǒng)提供的功能資源,方便用戶編程?

在前面各章中,已多次使用過以“#”開頭的預(yù)處理命令,如包含命令#include,宏定義命令#define等。在源程序中,這些命令都放在主函數(shù)之外,而且一般都放在源文件的開始位置,稱為預(yù)處理部分。

所謂預(yù)處理,是指編譯系統(tǒng)在對一個源程序進(jìn)行編譯之前,先對程序某些特殊命令進(jìn)行處理,再將處理結(jié)果和源程序一起編譯生成目標(biāo)程序。預(yù)處理是C語言系統(tǒng)的一個重要功能,它由預(yù)處理程序來完成。當(dāng)對一個源文件進(jìn)行編譯時,系統(tǒng)將自動引用預(yù)處理程序?qū)υ闯绦蛑械念A(yù)處理部分作處理,處理完畢自動進(jìn)入源程序的編譯。合理使用預(yù)處理功能可方便程序的編寫、閱讀、修改、移植和調(diào)試,能提高編程的效率,也有利于模塊化程序設(shè)計。

C語言系統(tǒng)提供了多種預(yù)處理功能,如宏定義、文件包含、條件編譯等。使用各種編譯預(yù)處理命令時應(yīng)注意以下幾點(diǎn):

(1)編譯預(yù)處理命令不是C語言的語句,一般放在程序的開頭,但也可以根據(jù)需要放在程序中間或程序末尾等位置。

(2)編譯預(yù)處理命令的書寫均以“#”開頭,因?yàn)椴皇荂語言的語句,所以末尾不加分號。

(3)一行只能書寫一條編譯預(yù)處理命令。

(4)編譯預(yù)處理命令多用于實(shí)現(xiàn)一種簡單替換功能,編譯時系統(tǒng)不進(jìn)行語法檢查。

10.1.1宏定義

宏定義的作用是用標(biāo)識符來代表一個字符串,即給字符串取名。一般是將一個復(fù)雜的字符串用一個簡單的標(biāo)識符代替,或?qū)⒁粋€不便于理解和記憶的標(biāo)識符用一個便于理解和記憶的標(biāo)識符代替??梢哉f,宏定義的目的與意義是簡化字符串或提高字符串的明晰性。編程時,可使用宏定義后的標(biāo)識符代替被定義的字符串,C編譯系統(tǒng)在編譯之前又將這些標(biāo)識符替換成被定義的字符串。宏定義分為不帶參數(shù)的宏定義(即無參宏定義)和帶參數(shù)的宏定義(即帶參宏定義)。

1.無參宏定義

無參宏定義的一般形式為

#define標(biāo)識符源字符串

其中,“標(biāo)識符”為所定義的宏名;“源字符串”可以是常數(shù)、表達(dá)式、格式串等。

例如:

#definePI3.1415926

經(jīng)此定義,程序就可以用PI代表3.141?592?6。顯然,能簡化書寫,提高符號的明晰性。預(yù)編譯時又要將源程序中所有宏名PI出現(xiàn)的位置用3.141?592?6來替換。

關(guān)于無參宏定義的幾點(diǎn)說明:

(1)宏名一般用大寫字母表示,以便與普通變量相區(qū)別。

(2)?#與define間一般不留空格,宏名兩側(cè)必須至少用一個(可以多個)空格分隔。

(3)宏定義用宏名代替一個字符串,并不管它的數(shù)據(jù)類型是什么,也不管詞法和語法是否正確,只作簡單的替換。

(4)?#define命令定義的宏名的作用范圍是從定義命令開始,到源程序文件結(jié)束,一般情況下,#define總是定義在文件開頭,不能在函數(shù)內(nèi)。還可以在程序中通過#undef提前終止宏名的作用域。

(5)宏定義中,宏名還可以出現(xiàn)在被定義的字符串中,但還原時又分層置換。例如:

#definePI3.1415926

#defineSPI*y*y(PI是已定義的宏名)

此時,S表示的串是3.1415926*y*y。

(6)宏定義是專用于預(yù)處理的一個名詞,它與變量定義的含義不同,只是在編譯時進(jìn)行的字符串的簡單替換,不分配內(nèi)存空間。它為編程提供了方便,能提高程序的通用性。

2.帶參宏定義

C語言允許宏帶參數(shù)。在宏定義中的參數(shù)稱為形式參數(shù),在宏調(diào)用中的參數(shù)稱為實(shí)際參數(shù)。對帶參數(shù)的宏,在調(diào)用中,不僅要求宏展開,而且要用實(shí)參去代換形參。

帶參宏定義的一般形式為

#define宏名(形參表)字符串

其中,在字符串中含有形參。

帶參宏調(diào)用的一般形式為

宏名(實(shí)參表);

例如:

#defineM(y)y*y+3*y//宏定義,y是形參

k=M(5);//宏調(diào)用,5是實(shí)參

定義了帶參數(shù)的宏M(y),y為宏的形參,即用M(y)來代替y*y+3*y。M(5)是宏調(diào)用,宏調(diào)用時,用實(shí)參5代替形參y。經(jīng)預(yù)處理,宏展開后的語句為

k=5*5+3*5;

關(guān)于帶參宏定義的幾點(diǎn)說明:

(1)在帶參宏定義中,形式參數(shù)不分配內(nèi)存單元,因此不必作類型定義。而宏調(diào)用中的實(shí)參有具體的值,要用它們代換形參,因此必須作類型說明。這是與函數(shù)中的情況不同的。在函數(shù)中,形參和實(shí)參是兩個不同的量,各有自己的作用域,調(diào)用時要把實(shí)參值賦予形參,進(jìn)行“值傳遞”。而在帶參宏中,只是符號代換,不存在值傳遞的問題。

(2)宏定義中的形參是標(biāo)識符,宏調(diào)用中的實(shí)參可以是表達(dá)式。

(3)在宏定義中,字符串內(nèi)的形參通常要用括號括起來,以避免出錯。例10.1中的宏定義(y)*(y)表達(dá)式的y都用括號括起來。如果去掉括號,把預(yù)處理命令改為

#defineSQR(y)y*y

則宏代換后的語句是“q=a+1*a+1;”。顯然將出現(xiàn)結(jié)果錯誤。

(4)函數(shù)調(diào)用和宏調(diào)用二者在形式上相似,但本質(zhì)上是完全不同的。宏定義也可用來定義多個語句,在宏調(diào)用時,把這些語句又代換到源程序內(nèi)。

10.1.2文件包含

文件包含命令的功能是把指定的文件插入該命令行位置取代該命令行,作為本程序文件的組成部分。

關(guān)于文件包含命令的幾點(diǎn)說明:

(1)包含命令中的文件名可以用雙引號括起來,也可以用尖括號括起來,主要區(qū)別在于系統(tǒng)查找文件的路徑不同。使用尖括號表示在包含文件目錄中查找(包含目錄是由用戶在設(shè)置環(huán)境時設(shè)置的),而不在源文件目錄中查找;使用雙引號則表示首先在當(dāng)前的源文件目錄中查找,若未找到,再到包含目錄中查找。這種使用形式更加通用。用戶編程時可根據(jù)自己文件所在的目錄來選擇一種命令形式。

(2)一個include命令只能指定一個被包含文件,若有多個文件要包含,則需用多個include命令。文件包含允許嵌套,即在一個被包含的文件中又可以包含另一個文件。

10.1.3條件編譯

預(yù)處理程序提供了條件編譯的功能,可以按不同的條件編譯不同的程序部分,因而產(chǎn)生不同的目標(biāo)代碼文件。這對于程序的移植和調(diào)試是很有用的。條件編譯有三種形式。

上面介紹的條件編譯當(dāng)然也可以用條件語句來實(shí)現(xiàn)。但是用條件語句將會對整個源程序進(jìn)行編譯,生成的目標(biāo)代碼程序比較長,而采用條件編譯,則根據(jù)條件只編譯其中的程序段1或程序段2,生成的目標(biāo)程序較短。如果條件選擇的程序段很長,采用條件編譯的方法是十分必要的。

10.2位運(yùn)算

何謂位運(yùn)算?C語言有哪些位運(yùn)算功能?位運(yùn)算就是對二進(jìn)制數(shù)的按位運(yùn)算。這種運(yùn)算是在計算機(jī)的硬件級上常進(jìn)行的運(yùn)算。很多系統(tǒng)程序中常要求在位(bit)一級進(jìn)行運(yùn)算或處理。C語言提供了位運(yùn)算的功能,這使得C語言既具有其他高級語言的特點(diǎn),又具備低級程序設(shè)計語言的功能。位運(yùn)算只能對整型或字符型數(shù)據(jù)進(jìn)行。C語言中有6種位運(yùn)算符,它們的作用、結(jié)合方向和優(yōu)先級見表10.1。

10.2.1位運(yùn)算符

1.位“與”運(yùn)算

位“與”運(yùn)算的符號為“&”,是對兩個二進(jìn)制數(shù)按位進(jìn)行邏輯“與”運(yùn)算。只有兩個二進(jìn)制數(shù)的運(yùn)算位均為1時,該位的運(yùn)算結(jié)果才為1,否則為0。

2.位“或”運(yùn)算

位“或”運(yùn)算的符號為“|”,是對兩個二進(jìn)制數(shù)按位進(jìn)行邏輯“或”運(yùn)算。只有兩個二進(jìn)制數(shù)的運(yùn)算位均為0時,該位的運(yùn)算結(jié)果才為0,否則為1。

按位“或”運(yùn)算通常用來對某些位置1或保留某些位。例如a=a?|?1,使a的最低位置1。

3.位“異或”運(yùn)算

位“異或”運(yùn)算的符號為“∧”,是對兩個二進(jìn)制數(shù)按位進(jìn)行邏輯“異或”運(yùn)算。兩個二進(jìn)制數(shù)的對應(yīng)位相異時,結(jié)果為1;相同時,結(jié)果為0。

4.位“取反”運(yùn)算

位“求反”運(yùn)算的符號為“~”,是對一個二進(jìn)制數(shù)逐位取反,即原為1,取反為0;原為0,取反為1。

5.左移運(yùn)算

左移運(yùn)算的符號為“<<”,是把一個二進(jìn)制數(shù)左移指定的位數(shù)。左移時,高位丟掉,低位補(bǔ)0。要左移的數(shù)據(jù)對象在運(yùn)算符左面,左移位數(shù)在運(yùn)算符右面。

6.右移運(yùn)算

右移運(yùn)算的符號為“>>”,是把一個二進(jìn)制數(shù)右移指定的位數(shù)。右移時高位補(bǔ)0,低位丟掉。要右移的數(shù)據(jù)對象在運(yùn)算符左面,右移位數(shù)在運(yùn)算符右面。

10.2.2位處理程序設(shè)計舉例

在硬件接口上,常有輸入狀態(tài)端口的狀態(tài)信息,可根據(jù)狀態(tài)進(jìn)行不同處理。例如,與打印機(jī)交換數(shù)據(jù)時要檢測打印機(jī)的狀態(tài)“BUSY”,如狀態(tài)位為1,則等待,如為0則向打印機(jī)送數(shù)據(jù)。循環(huán)移位也是計算機(jī)系統(tǒng)常有的邏輯處理方式。下面針對這兩種問題來說明位處理程序設(shè)計的方法。

例10.5輸入一個十六進(jìn)制數(shù)據(jù)和一個狀態(tài)數(shù)據(jù),檢測狀態(tài)數(shù)據(jù)的最低位是否為0,為0,則截取數(shù)據(jù)的4~7位輸出,為1則輸出“BUSY”。

編程思路:要檢測某一位是否為0,只要設(shè)置一個對應(yīng)位上為1、其他位上為0的二進(jìn)制數(shù),用這個二進(jìn)制數(shù)和被檢測的二進(jìn)制數(shù)進(jìn)行“與”運(yùn)算,結(jié)果為0,則被檢測位為0。要截取數(shù)據(jù)的4~7位,只要設(shè)置一個4~7位為1,其他位0的二進(jìn)制數(shù),與被截取的數(shù)據(jù)進(jìn)行“與”運(yùn)算,則數(shù)據(jù)的4~7位保留下來,其他數(shù)位均為0,然后右移4位,將保留數(shù)位移到最低位即可。

例10.6將a右循環(huán)移位k位。如果a中有二進(jìn)制數(shù)1101111110101011,設(shè)右循環(huán)移位3位,則移位后的結(jié)果應(yīng)為0111101111110101。

編程思路:C語言中的移位運(yùn)算只能實(shí)現(xiàn)邏輯移位,不能實(shí)現(xiàn)循環(huán)移位,移位數(shù)據(jù)對象是變量。變量的值在計算機(jī)內(nèi)是以二進(jìn)制數(shù)存儲的。要實(shí)現(xiàn)循環(huán)移位,必須采取一定算法。為滿足題目要求,設(shè)字長為16位,可采用以下步驟:

(1)將a的低16-k位先邏輯左移到b的高位端,低16-k位全補(bǔ)為0,可用下面語句來實(shí)現(xiàn):

b=a<<(16-k);

(2)將a邏輯右移k位,高k位補(bǔ)0,可用下面語句來實(shí)現(xiàn):

c=a>>k;

10.2.3位段(位域)

如前所述,C語言的各種運(yùn)算都是以字作為最基本單位進(jìn)行的。但在某些特殊情況下,為節(jié)省存儲空間,簡化處理,允許信息存儲時可以不占用一個完整的字存儲單元,而只需占用幾個二進(jìn)制位。例如在存放一個開關(guān)量時,只有0和1兩種狀態(tài),用一位二進(jìn)制位即可。為此,C語言又提供了一種數(shù)據(jù)結(jié)構(gòu),稱為位段或位域。

所謂位段,是把一個字單元中的二進(jìn)制位劃分為幾個不同的區(qū)段,并說明每個區(qū)段的位數(shù)。每個區(qū)段有一個位段名,允許在程序中按位段名進(jìn)行操作。這樣就可以把幾個不同的對象用一個字單元的幾個二進(jìn)制位段來表示。

位段定義就是把一個存儲器字單元定義成一個位段結(jié)構(gòu)體,一個位段是結(jié)構(gòu)體中的一個成員。位段定義的一般形式為

其中,類型是指位段中數(shù)據(jù)的類型;位段名是位段引用的標(biāo)識符;位數(shù)是位段所占的存儲位,即二進(jìn)制位數(shù)。位段、位數(shù)之和小于或等于系統(tǒng)字長。位段名可以沒有,表示空位段。位段的使用采用引用結(jié)構(gòu)體成員的方法。例如:

定義了3個有名位段a、b和c,分別占4位、3位和1位,存儲無符號類型數(shù)。另外,包含一個無名位段,占4位,因?yàn)闊o名位段不能引用,所以相當(dāng)于空位段,只占據(jù)位數(shù)。字長是32位的系統(tǒng),定義位段后,字單元還剩余32-4-4-3-1=20(位),用“inti;”說明,表示可以存放整型數(shù)。若要給字段賦值,可用以下賦值語句:

關(guān)于位段定義和使用的幾點(diǎn)說明:

(1)無名字段只用于填充或調(diào)整位置,是不能使用的。

(2)一個位段必須存儲在一個單元中,不能跨兩個單元。如果第一個單元不能容納下一個位段,則從下一個單元起存放該位段。若某一位段要從另一個單元開始存放,則可以采用如下形式定義:

(3)位段可以在數(shù)值表達(dá)式中引用,系統(tǒng)自動轉(zhuǎn)換成整型數(shù)。例如:

bit.a+5/bitdata.b

是正確的。

實(shí)操訓(xùn)練圖10.1打印機(jī)狀態(tài)寄存器

實(shí)訓(xùn)任務(wù)十學(xué)習(xí)位運(yùn)算應(yīng)用程序設(shè)計的方法實(shí)訓(xùn)項(xiàng)目打印機(jī)接口有一狀態(tài)寄存器,其信息定義如圖10.1所示。

設(shè)計程序,模擬讀取狀態(tài)寄存器,測試其狀態(tài),輸出相應(yīng)狀態(tài)的信息。輸入/輸出界面可參照圖10.2所示。圖10.2實(shí)訓(xùn)項(xiàng)目界面式樣

實(shí)訓(xùn)指導(dǎo)

1.設(shè)計程序

(1)定義一個短整型變量模擬狀態(tài)寄存器,從鍵盤輸入一個兩位十六進(jìn)制數(shù)(8位二進(jìn)制數(shù))來模擬讀取狀態(tài)寄存器的狀態(tài)信息。

(2)通過位“與”運(yùn)算,測試相關(guān)狀態(tài)。設(shè)置某一狀態(tài)對應(yīng)位為1、其他位為0的二進(jìn)制數(shù),該數(shù)和狀態(tài)寄存器內(nèi)容進(jìn)行位“與”運(yùn)算,如果運(yùn)算結(jié)果為0,則該位的狀態(tài)值為0,否則該位狀態(tài)值為1。

2.測試運(yùn)行程序

從鍵盤分別輸入反映打印機(jī)每一種狀態(tài)的狀態(tài)字,檢測運(yùn)行結(jié)果是否正確

溫馨提示

  • 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論