跟著肯哥(不是我)學預處理機制
預處理類別
宏定義:#define
- 將文本替換為表達式或語句
條件編譯:#ifdef
、#ifndef
和#if
、#elif
、#endif
- 根據標識符是否被定義選擇編譯代碼
頭文件包含:#include
- 將其他文件(通常是頭文件)包含到當前文件中,以便在當前文件中使用頭文件中定義的內容
預處理流程
- 預處理指令識別
- 宏替換
- 條件編譯
- 頭文件包含
- 行連接處理
- 宏展開和條件編譯的遞歸處理
預處理指令識別
掃描源代碼并識別以#
開頭的預處理指令。
宏替換
預處理器根據宏定義將代碼中的宏名稱替換為指定的文本。
可以是常量替換,也可以是帶參數的宏函數替換
預處理器會根據宏定義展開宏
條件編譯
根據條件選擇性地編譯不同的代碼塊。
#ifdef
、#ifndef
和#if
、#elif
、#endif
頭文件包含
通過#include
指令,將其他文件(通常是頭文件)包含到當前文件中,以便在當前文件中使用頭文件中定義的內容
預處理的行連接處理
在C語言中,行連接處理是預處理階段的一部分,用于將一行代碼書寫為多行,以保持代碼可讀性。
行連接操作通過反斜杠\
字符實現。一行代碼以反斜杠字符結尾時,該行代碼將與下一行自動連接為一行。
換行之后的進位也會被當作空格輸出出來。
行連接在預處理階段,在編譯階段看到代碼時,已經是連接在一起的一行。這種處理不會影響編譯器的語義分析和中間代碼。
宏展開和條件編譯的遞歸處理
在進行宏展開和條件編譯時,如果遇到新的預處理指令,預處理器會遞歸地處理這些指令。肯呢個會觸發更多的宏展開和條件編譯。
刪除注釋
預處理器將源代碼中的注釋刪除,注釋在預處理階段無需保留,不會影響編譯器的輸出。
預編譯的警告信息和錯誤信息
可以使用#error
和#warning
預處理指令來生成編譯錯誤和警告信息。這些指令在預處理時發出特定的錯誤或警告信息,讓開發者知道代碼中存在的問題或需要注意的地方
#error
和#warning
指令生成的信息只會在預處理階段發出,而不會影響到最終的目標代碼,它們在編譯階段不會生成任何錯誤或警告信息。
查看預處理后的源文件
以肯哥用的GCC為例。
可以使用-E
選項來查看預處理后的源文件。只進行預處理操作,不進行編譯、匯編和鏈接。將預處理后的源文件輸出到標準輸出流,一般是控制臺。
gcc -E example.c
編譯器會將預處理后的內容輸出到控制臺。
如果你想將預處理后的源文件保存到一個文件中,可以使用重定向操作符>
將輸出重定向到一個文件中。
gcc -E example.c > preprocessed.c
上述命令會將預處理后的源文件保存到名為preprocessed.c
的文件中。
重點強調
- 宏定義的命名規范
- 宏定義與函數調用的沖突
#include
不單單是只能包含頭文件:include
的本質就是純文本包含。- 善用條件編譯:在龐大工程代碼的配置裁剪工作中,絕大多數的技術手段就是利用條件編譯,對不同的代碼選用和刪除,達到代碼裁剪的效果。