版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
編譯預處理與位運算
——C語言的附加功能10.1編譯預處理10.2位運算實操訓練課外練習
10.1編譯預處理
如何使用C語言系統(tǒng)提供的功能資源,方便用戶編程?
在前面各章中,已多次使用過以“#”開頭的預處理命令,如包含命令#include,宏定義命令#define等。在源程序中,這些命令都放在主函數(shù)之外,而且一般都放在源文件的開始位置,稱為預處理部分。
所謂預處理,是指編譯系統(tǒng)在對一個源程序進行編譯之前,先對程序某些特殊命令進行處理,再將處理結(jié)果和源程序一起編譯生成目標程序。預處理是C語言系統(tǒng)的一個重要功能,它由預處理程序來完成。當對一個源文件進行編譯時,系統(tǒng)將自動引用預處理程序?qū)υ闯绦蛑械念A處理部分作處理,處理完畢自動進入源程序的編譯。合理使用預處理功能可方便程序的編寫、閱讀、修改、移植和調(diào)試,能提高編程的效率,也有利于模塊化程序設(shè)計。
C語言系統(tǒng)提供了多種預處理功能,如宏定義、文件包含、條件編譯等。使用各種編譯預處理命令時應注意以下幾點:
(1)編譯預處理命令不是C語言的語句,一般放在程序的開頭,但也可以根據(jù)需要放在程序中間或程序末尾等位置。
(2)編譯預處理命令的書寫均以“#”開頭,因為不是C語言的語句,所以末尾不加分號。
(3)一行只能書寫一條編譯預處理命令。
(4)編譯預處理命令多用于實現(xiàn)一種簡單替換功能,編譯時系統(tǒng)不進行語法檢查。
10.1.1宏定義
宏定義的作用是用標識符來代表一個字符串,即給字符串取名。一般是將一個復雜的字符串用一個簡單的標識符代替,或?qū)⒁粋€不便于理解和記憶的標識符用一個便于理解和記憶的標識符代替??梢哉f,宏定義的目的與意義是簡化字符串或提高字符串的明晰性。編程時,可使用宏定義后的標識符代替被定義的字符串,C編譯系統(tǒng)在編譯之前又將這些標識符替換成被定義的字符串。宏定義分為不帶參數(shù)的宏定義(即無參宏定義)和帶參數(shù)的宏定義(即帶參宏定義)。
1.無參宏定義
無參宏定義的一般形式為
#define標識符源字符串
其中,“標識符”為所定義的宏名;“源字符串”可以是常數(shù)、表達式、格式串等。
例如:
#definePI3.1415926
經(jīng)此定義,程序就可以用PI代表3.141?592?6。顯然,能簡化書寫,提高符號的明晰性。預編譯時又要將源程序中所有宏名PI出現(xiàn)的位置用3.141?592?6來替換。
關(guā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)宏定義是專用于預處理的一個名詞,它與變量定義的含義不同,只是在編譯時進行的字符串的簡單替換,不分配內(nèi)存空間。它為編程提供了方便,能提高程序的通用性。
2.帶參宏定義
C語言允許宏帶參數(shù)。在宏定義中的參數(shù)稱為形式參數(shù),在宏調(diào)用中的參數(shù)稱為實際參數(shù)。對帶參數(shù)的宏,在調(diào)用中,不僅要求宏展開,而且要用實參去代換形參。
帶參宏定義的一般形式為
#define宏名(形參表)字符串
其中,在字符串中含有形參。
帶參宏調(diào)用的一般形式為
宏名(實參表);
例如:
#defineM(y)y*y+3*y//宏定義,y是形參
…
k=M(5);//宏調(diào)用,5是實參
…
定義了帶參數(shù)的宏M(y),y為宏的形參,即用M(y)來代替y*y+3*y。M(5)是宏調(diào)用,宏調(diào)用時,用實參5代替形參y。經(jīng)預處理,宏展開后的語句為
k=5*5+3*5;
關(guān)于帶參宏定義的幾點說明:
(1)在帶參宏定義中,形式參數(shù)不分配內(nèi)存單元,因此不必作類型定義。而宏調(diào)用中的實參有具體的值,要用它們代換形參,因此必須作類型說明。這是與函數(shù)中的情況不同的。在函數(shù)中,形參和實參是兩個不同的量,各有自己的作用域,調(diào)用時要把實參值賦予形參,進行“值傳遞”。而在帶參宏中,只是符號代換,不存在值傳遞的問題。
(2)宏定義中的形參是標識符,宏調(diào)用中的實參可以是表達式。
(3)在宏定義中,字符串內(nèi)的形參通常要用括號括起來,以避免出錯。例10.1中的宏定義(y)*(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)于文件包含命令的幾點說明:
(1)包含命令中的文件名可以用雙引號括起來,也可以用尖括號括起來,主要區(qū)別在于系統(tǒng)查找文件的路徑不同。使用尖括號表示在包含文件目錄中查找(包含目錄是由用戶在設(shè)置環(huán)境時設(shè)置的),而不在源文件目錄中查找;使用雙引號則表示首先在當前的源文件目錄中查找,若未找到,再到包含目錄中查找。這種使用形式更加通用。用戶編程時可根據(jù)自己文件所在的目錄來選擇一種命令形式。
(2)一個include命令只能指定一個被包含文件,若有多個文件要包含,則需用多個include命令。文件包含允許嵌套,即在一個被包含的文件中又可以包含另一個文件。
10.1.3條件編譯
預處理程序提供了條件編譯的功能,可以按不同的條件編譯不同的程序部分,因而產(chǎn)生不同的目標代碼文件。這對于程序的移植和調(diào)試是很有用的。條件編譯有三種形式。
上面介紹的條件編譯當然也可以用條件語句來實現(xiàn)。但是用條件語句將會對整個源程序進行編譯,生成的目標代碼程序比較長,而采用條件編譯,則根據(jù)條件只編譯其中的程序段1或程序段2,生成的目標程序較短。如果條件選擇的程序段很長,采用條件編譯的方法是十分必要的。
10.2位運算
何謂位運算?C語言有哪些位運算功能?位運算就是對二進制數(shù)的按位運算。這種運算是在計算機的硬件級上常進行的運算。很多系統(tǒng)程序中常要求在位(bit)一級進行運算或處理。C語言提供了位運算的功能,這使得C語言既具有其他高級語言的特點,又具備低級程序設(shè)計語言的功能。位運算只能對整型或字符型數(shù)據(jù)進行。C語言中有6種位運算符,它們的作用、結(jié)合方向和優(yōu)先級見表10.1。
10.2.1位運算符
1.位“與”運算
位“與”運算的符號為“&”,是對兩個二進制數(shù)按位進行邏輯“與”運算。只有兩個二進制數(shù)的運算位均為1時,該位的運算結(jié)果才為1,否則為0。
2.位“或”運算
位“或”運算的符號為“|”,是對兩個二進制數(shù)按位進行邏輯“或”運算。只有兩個二進制數(shù)的運算位均為0時,該位的運算結(jié)果才為0,否則為1。
按位“或”運算通常用來對某些位置1或保留某些位。例如a=a?|?1,使a的最低位置1。
3.位“異或”運算
位“異或”運算的符號為“∧”,是對兩個二進制數(shù)按位進行邏輯“異或”運算。兩個二進制數(shù)的對應位相異時,結(jié)果為1;相同時,結(jié)果為0。
4.位“取反”運算
位“求反”運算的符號為“~”,是對一個二進制數(shù)逐位取反,即原為1,取反為0;原為0,取反為1。
5.左移運算
左移運算的符號為“<<”,是把一個二進制數(shù)左移指定的位數(shù)。左移時,高位丟掉,低位補0。要左移的數(shù)據(jù)對象在運算符左面,左移位數(shù)在運算符右面。
6.右移運算
右移運算的符號為“>>”,是把一個二進制數(shù)右移指定的位數(shù)。右移時高位補0,低位丟掉。要右移的數(shù)據(jù)對象在運算符左面,右移位數(shù)在運算符右面。
10.2.2位處理程序設(shè)計舉例
在硬件接口上,常有輸入狀態(tài)端口的狀態(tài)信息,可根據(jù)狀態(tài)進行不同處理。例如,與打印機交換數(shù)據(jù)時要檢測打印機的狀態(tài)“BUSY”,如狀態(tài)位為1,則等待,如為0則向打印機送數(shù)據(jù)。循環(huán)移位也是計算機系統(tǒng)常有的邏輯處理方式。下面針對這兩種問題來說明位處理程序設(shè)計的方法。
例10.5輸入一個十六進制數(shù)據(jù)和一個狀態(tài)數(shù)據(jù),檢測狀態(tài)數(shù)據(jù)的最低位是否為0,為0,則截取數(shù)據(jù)的4~7位輸出,為1則輸出“BUSY”。
編程思路:要檢測某一位是否為0,只要設(shè)置一個對應位上為1、其他位上為0的二進制數(shù),用這個二進制數(shù)和被檢測的二進制數(shù)進行“與”運算,結(jié)果為0,則被檢測位為0。要截取數(shù)據(jù)的4~7位,只要設(shè)置一個4~7位為1,其他位0的二進制數(shù),與被截取的數(shù)據(jù)進行“與”運算,則數(shù)據(jù)的4~7位保留下來,其他數(shù)位均為0,然后右移4位,將保留數(shù)位移到最低位即可。
例10.6將a右循環(huán)移位k位。如果a中有二進制數(shù)1101111110101011,設(shè)右循環(huán)移位3位,則移位后的結(jié)果應為0111101111110101。
編程思路:C語言中的移位運算只能實現(xiàn)邏輯移位,不能實現(xiàn)循環(huán)移位,移位數(shù)據(jù)對象是變量。變量的值在計算機內(nèi)是以二進制數(shù)存儲的。要實現(xiàn)循環(huán)移位,必須采取一定算法。為滿足題目要求,設(shè)字長為16位,可采用以下步驟:
(1)將a的低16-k位先邏輯左移到b的高位端,低16-k位全補為0,可用下面語句來實現(xiàn):
b=a<<(16-k);
(2)將a邏輯右移k位,高k位補0,可用下面語句來實現(xiàn):
c=a>>k;
10.2.3位段(位域)
如前所述,C語言的各種運算都是以字作為最基本單位進行的。但在某些特殊情況下,為節(jié)省存儲空間,簡化處理,允許信息存儲時可以不占用一個完整的字存儲單元,而只需占用幾個二進制位。例如在存放一個開關(guān)量時,只有0和1兩種狀態(tài),用一位二進制位即可。為此,C語言又提供了一種數(shù)據(jù)結(jié)構(gòu),稱為位段或位域。
所謂位段,是把一個字單元中的二進制位劃分為幾個不同的區(qū)段,并說明每個區(qū)段的位數(shù)。每個區(qū)段有一個位段名,允許在程序中按位段名進行操作。這樣就可以把幾個不同的對象用一個字單元的幾個二進制位段來表示。
位段定義就是把一個存儲器字單元定義成一個位段結(jié)構(gòu)體,一個位段是結(jié)構(gòu)體中的一個成員。位段定義的一般形式為
其中,類型是指位段中數(shù)據(jù)的類型;位段名是位段引用的標識符;位數(shù)是位段所占的存儲位,即二進制位數(shù)。位段、位數(shù)之和小于或等于系統(tǒng)字長。位段名可以沒有,表示空位段。位段的使用采用引用結(jié)構(gòu)體成員的方法。例如:
定義了3個有名位段a、b和c,分別占4位、3位和1位,存儲無符號類型數(shù)。另外,包含一個無名位段,占4位,因為無名位段不能引用,所以相當于空位段,只占據(jù)位數(shù)。字長是32位的系統(tǒng),定義位段后,字單元還剩余32-4-4-3-1=20(位),用“inti;”說明,表示可以存放整型數(shù)。若要給字段賦值,可用以下賦值語句:
關(guān)于位段定義和使用的幾點說明:
(1)無名字段只用于填充或調(diào)整位置,是不能使用的。
(2)一個位段必須存儲在一個單元中,不能跨兩個單元。如果第一個單元不能容納下一個位段,則從下一個單元起存放該位段。若某一位段要從另一個單元開始存放,則可以采用如下形式定義:
(3)位段可以在數(shù)值表達式中引用,系統(tǒng)自動轉(zhuǎn)換成整型數(shù)。例如:
bit.a+5/bitdata.b
是正確的。
實操訓練圖10.1打印機狀態(tài)寄存器
實訓任務十學習位運算應用程序設(shè)計的方法實訓項目打印機接口有一狀態(tài)寄存器,其信息定義如圖10.1所示。
設(shè)計程序,模擬讀取狀態(tài)寄存器,測試其狀態(tài),輸出相應狀態(tài)的信息。輸入/輸出界面可參照圖10.2所示。圖10.2實訓項目界面式樣
實訓指導
1.設(shè)計程序
(1)定義一個短整型變量模擬狀態(tài)寄存器,從鍵盤輸入一個兩位十六進制數(shù)(8位二進制數(shù))來模擬讀取狀態(tài)寄存器的狀態(tài)信息。
(2)通過位“與”運算,測試相關(guān)狀態(tài)。設(shè)置某一狀態(tài)對應位為1、其他位為0的二進制數(shù),該數(shù)和狀態(tài)寄存器內(nèi)容進行位“與”運算,如果運算結(jié)果為0,則該位的狀態(tài)值為0,否則該位狀態(tài)值為1。
2.測試運行程序
從鍵盤分別輸入反映打印機每一種狀態(tài)的狀態(tài)字,檢測運行結(jié)果是否正確
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 關(guān)于規(guī)范駕駛員制度
- 水庫水質(zhì)自動監(jiān)測系統(tǒng)
- 遠程會診制度資料規(guī)范
- 規(guī)范AB角替崗制度
- 中學內(nèi)控制度規(guī)范
- 閉店規(guī)范準則制度匯編
- 混合土壤改良技術(shù)實施方案
- 制度仍需進一步規(guī)范
- 落實晨午檢規(guī)范制度
- 云賬號管理制度規(guī)范
- 泵車日常管理辦法
- 骨科術(shù)后疼痛評估與護理查房
- 輸液泵的使用培訓課件
- 中醫(yī)針灸治療婦科疾病
- 25年自來水考試試題大題及答案
- 中職數(shù)學高等教育出版社
- 腫瘤科一科一品十佳案例
- 25春國家開放大學《學前兒童音樂教育活動指導》期末大作業(yè)答案
- 提優(yōu)點7 衍生數(shù)列問題
- 2025-2030中國制藥工業(yè)AGV行業(yè)市場發(fā)展趨勢與前景展望戰(zhàn)略研究報告
- 2025濰坊護理職業(yè)學院輔導員考試題庫
評論
0/150
提交評論