




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第C語言零基礎徹底掌握預處理下篇目錄1、條件編譯1.1條件編譯如何使用1.2用#if模擬#ifdef1.3為何要有條件編譯2、文件包含2.1#include究竟干了什么2.2防止頭文件重復包含的條件編譯是如何做到的3、選學內容3.1#error預處理3.2#line預處理3.3#pragma預處理3.3.1#pragmamessage3.3.2#pragmaonce3.3.3#pragmawarning3.3.4#pragmapack3.4#和##
1、條件編譯
1.1條件編譯如何使用
C語言提供的條件編譯的功能可以讓我們按照不同的條件去編譯不同的程序部分,從而產生不同目標代碼文件。
第一種形式:
程序段1
程序段2
它的功能是,如果標識符已經被#define定義了,則只會對程序段1進行編譯,不會對程序段2進行編譯,如果沒有被定義則反之,如果我們不需要程序段2,也可以省去#else和他對應的程序段。
第二種形式:
程序段1
程序段2
第二種形式與第一種形式的區別是將ifdef改為ifndef,它的功能是,如果標識符沒有被#dfine定義,則對程序段1進行編譯,不會對程序段2進行編譯,如果被定義了則反之,如果我們不需要程序段2,也可以省去#else和他對應的程序段。
第三種形式:
程序段1
程序段2
第三種形式的功能是:如果常量表達式的值為真(非0),則對程序段1進行編譯,否則對程序段2進行編譯,因此可以使程序在不同條件下,完成不同的功能。
至于里面還可以添加#elif命令,意義與elseif相同,形成一個ifelse階梯狀語句,可進行多種編譯選擇。
注意:如果定義空宏則會報錯,因為#if后面必須要更常量表達式!
1.2用#if模擬#ifdef
此代碼的意思是,如果PRINT宏被定義了,則執行第一個打印函數,否則執行第二個打印函數,同時我們也可以模擬#ifndef,只需前面加個邏輯非就可以!,例如:#if(!defined(PRINT))
就這樣完了嗎?其實并沒有,在更復雜的項目中,往往會出現兩個或多個宏需要同時定義才能滿足需求,我舉一個很簡單的例子,如果我定義了C宏和CPP宏,我才可以編譯所對應的代碼:
如上代碼就需要兩個宏都被定義才能編譯下面的程序段,相信學習過邏輯與的小伙伴應該很容易理解吧,那么我們如果需要兩個都未定義才能編譯下面的程序段呢?如何寫?
兩個都未定義才編譯:#if(!defined(C)!defined(CPP))前面分別加邏輯非就可以!
或者:#if(!(defined(C)||defined(CPP)))本代碼中邏輯或只要有一個被定義,就為真,然后執行邏輯非,這樣也能保證兩個都未定義才進行編譯!
至于最后用不用大括號給括起來,我的建議是括起來,這樣我們閱讀代碼會更直觀!
既然出現了邏輯與,是不是也可以出現邏輯或呢?當然上面已經有例子了,但是這里我就不一一演示了,感興趣的可以下來自己去嘗試一下。
條件編譯支持嵌套:
這里其實和我們平常用的if嵌套式是似的,也很容易理解,這里我們就不細說,有一點要注意的就是,條件編譯每個#if都需要有對應的#endif來結束
1.3為何要有條件編譯
我們先對我們上面2小節的內容做一個總結:條件編譯本質上是讓編譯器對代碼進行裁剪!
本質認識:條件編譯,其實就是編譯器根據實際情況,對代碼進行裁剪,而這里實際情況,取決于代碼平臺,代碼本身的業務邏輯。
可以只保留當前最需要的代碼邏輯,其他去掉,可以減少生成代碼的大小可以寫出跨平臺的代碼,讓一個具體業務,在不同平臺編譯的時候,可以有同樣的表現
條件編譯都用在哪些地方呢?
張三有個公司,公司有個項目,項目對應的軟件又有專業版,免費版,精簡版等等...
難道每個版本都對應著不同的代碼嗎?不是的,這樣維護起來太麻煩了,其實所謂不同的版本,本質就是功能上的有和無,所以在技術層面上,為了更好的維護,當然可以使用條件編譯,需要哪個版本,就是用條件編譯裁剪就行。
著名的Linux內核,功能上,其實也是用條件編譯進行功能裁剪的,用來滿足不同平臺的軟件。
2、文件包含
2.1#include究竟干了什么
我相信#include對于每個編程小伙伴來說都不陌生,很多人寫C語言第一件事就是寫上#includestdio.h可能老師會告訴你們這是包含標準輸入輸出頭文件,至于如何包含的,可能不會跟你講。那今天我們就來通過預處理來看一看到底是如何包含的:
我們來寫上一小段代碼:
前面說過,預處理會將頭文件展開,去注釋,宏替換,條件編譯等等
在Linux環境下我們可以執行命令:gcc-Etest.c-otest.i保留預處理之后的文件并命名為test.i
為了更好的對比,我們執行vim命令模式下的vs指令:vs/sur/include/tdio.h也就是打開標準輸入輸出的頭文件:
看到預處理的結果之后,發現文件大小比我們實際代碼要大得多!
結論:#include本質是把頭文件相關內容,拷貝到源文件中。
2.2防止頭文件重復包含的條件編譯是如何做到的
既然我們會包含頭文件,那有沒有可能存在頭文件重復被包含的可能性呢?導致我們頭文件被重復拷貝?
這里可能會有很多老師也教過,同學們啊,我們寫頭文件的時候一定要寫如下代碼啊,這是防止頭文件重復包含的啊:
#ifndef_TEST_H_
#define_TEST_H_
#includestdio.h
#defineMAX999
intg_val=10;
externvoidPrint();
#endif
如上代碼很多小伙伴都知道在#ifndef_TEST_H_和#endif之間寫的頭文件包含,宏定義,全局變量,函數聲明,都不會被重復拷貝,為什么呢?他是如何做到的?我們實驗證明(如下兩張圖最右邊是預處理之后的結果):
如下代碼是沒有帶上條件編譯防止頭文件重復包含,但在源文件已經重復包含的例子:
我們加上#ifndef_TEST_H_和#endif在來看重復包含的效果:
已經沒有重復拷貝的情況了,看來確實有防止頭文件重復包含的效果!
那么這條語句是如何做到的呢?
我們前面學過#ifndef如果沒有定義這個宏,則執行后續語句,當第一次我們頭文件展開的時候,確實沒有定義_TEST_H_這個宏,所以會執行后續的語句,但是在第一次展開的時候我們立馬定義了_TEST_H_宏,所以我們重復包含頭文件第二次展開的時候,這個宏已經被定義了,所以也就不會去執行#ifndef后續語句了!
結論:所有頭文件都得帶上條件編譯,防止頭文件重復包含!當然也可以直接#pragmaonce
重復包含的一定會報錯嗎?顯然是不會的,但是會引起多次拷貝,會影響編譯效率。
3、選學內容
3.1#error預處理
3.2#line預處理
intmain()
printf("%s,%d\n",__FILE__,__LINE__);//C預定義符號,代表當前文件名和代碼行號
#line60"hehe.h"http://定制化完成
printf("%s,%d\n",__FILE__,__LINE__);
return0;
}
本質其實是可以定制化你的文件名稱和代碼行號,很少使用!
3.3#pragma預處理
3.3.1#pragmamessage
message參數他能在編譯信息輸出窗口中輸出相應的信息,這對于源代碼信息的控制是非常重要的。
#defineTEST
intmain()
#ifdefTEST
#pragmamessage("TESTmacoractivated!")
#endif
return0;
}
當我們定義了TEST這個宏后,應用程序在編譯時就會在編譯輸出窗口里顯示TESTmacoractivated!因此我們就不會因為不記得自己定義的一些宏而著急了!
3.3.2#pragmaonce
這個還是比較常用的,只要在頭文件的最開始加入這條指令就能夠保證頭文件被編譯一次,但是考慮到兼容性的問題,并沒有太多的使用。
3.3.3#pragmawarning
#pragmawarning(disable:450734;once:4385;error:164)
//等價于:
#pragmawarning(disable:450734)//不顯示4507和34號警告信息
#pragmawarning(once:4385)//4385號警告信息僅報告一次
#pragmawarning(error:164)//把164號警告信息作為一個錯誤
當使用windowsvs環境的小伙伴們,在使用庫函數的時候比如scanf會說這個函數不安全,推薦你使用scanf_s,那我們要保證代碼可以移植性如何辦呢?通過查看報錯發現是4996報錯,那我們則可以:
#pragmawarning(disable:4996)//這樣就解決問題了!
3.3.4#pragmapack
設置結構體內存對齊,我們還沒更新到結構體,加上用的并不算多,所以感興趣的可以先去自行研究哦。
3.4#和##
假設說我們今天定義了一個打印宏:
#definePRINT(x)printf("helloxis%d.\n",((x)*(x)))
調用宏PRINT(8);則會輸出:helloxis64.
如果你希望字符串中包含宏參數,那我們就可以使用#,它可以把語言符號轉換成字符串:
#define
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 能源審計在制漿造紙行業節能改造中的應用考核試卷
- 租賃市場消費者行為研究考核試卷
- 清潔生產技術在化妝品企業品牌戰略中的應用考核試卷
- 光纖網絡運維管理體系建設考核試卷
- 部編道德與法治七年級上冊第一單元成長的節拍測試卷
- 2025年中國GRC素線數據監測報告
- 2025年中國COD排放總量在線監測儀數據監測研究報告
- 2025年中國30對旋卡式電纜分線盒數據監測研究報告
- 2025至2030年中國鑄鋼鐵合頁市場分析及競爭策略研究報告
- 2025至2030年中國重力式貨架鋼木托盤市場分析及競爭策略研究報告
- 5E教學模式研究現狀與提升策略
- 2024年糧油倉儲管理員理論知識競賽理論考試題庫500題(含答案)
- T-FSS 81-2023 佛山標準 食品包裝用玻璃瓶罐
- 【國網-變電運維】刀閘控制回路及五防(統一格式版本)
- 政府投資項目發改委審批程序課件
- 根管治療期間疼痛的處理
- 客服兼職聘用合同范例
- 調味品供應合同范本
- 垃圾清運方案、安全作業制度、環保管理制度
- 【互聯網消費金融風險管控探究:以螞蟻花唄ABS為例(論文)11000字】
- 安全操作規程匯編(服裝廠)
評論
0/150
提交評論