預處理功能是c語言特有的功能,它是在對源程式正式編譯前由預處理程式完成的,程式設計師在程式中用預處理命令來呼叫這些功能。
巨集定義可以帶有引數,巨集呼叫時是以實參代換形參,而不是「值傳送」。
為了避免巨集代換時發生錯誤,巨集定義中的字串應加括號,字串**現的形式引數兩邊也應加括號。
檔案包含是預處理的乙個重要功能,它可用來把多個原始檔連線成乙個原始檔進行編譯,結果將生成乙個目標檔案。
條件編譯允許只編譯源程式中滿足條件的程式段,使生成的目標程式較短,從而減少了記憶體的開銷並提高了程式的效率。
使用預處理功能便於程式的修改、閱讀、移植和除錯,也便於實現模組化程式設計。
#define預處理指令和其他預處理指令一樣,以#號作為一行的開始。ansi和後來的標準都允許#號前有空格或製表符,而且還允許在#和指令的其餘部分之間有空格。但是舊版的c要求指令從一行最左邊開始,而且#和其餘部分之間不能有空格。指令可以出現在原始檔的任何地方,其定義從質量出現的地方到該檔案末尾有效。我們大量使用#define指令來定義明示常量(也叫符號常量)。
示例:
/* preproc.c -- ****** preprocessor examples */
#include
#define two 2
/* you can use comments if you like */
#define ow "consistency is the last refuge of the unimagina\
tive. - oscar wilde"
/* a backslash continues a definition */
/* to the next line */
#define four two*two
#define px printf("x is %d.\n", x)
#define fmt "x is %d.\n"
intmain
(void
)
每行#define(邏輯行)都由3部分組成。第一部分是#define指令本身。第二部分是選定的縮寫,也成為巨集,巨集的名稱必須遵循c變數的命名規則。第三部分(指令行的其餘部分)稱為**替換列表或替換體。一旦預處理器在程式中找到巨集的例項後,就會用替換體代替該巨集。從巨集程式設計最終替換文字的過程稱為巨集展開。**注意,可以在#define行使用標準c注釋。
巨集可以代表任何字串,甚至可以表示整個c表示式。
巨集定義還可以包含其他巨集(一些編譯器不支援這種巢狀功能)。
printf
(fmt, x)
;
變成了
printf("x is %d.\n", x);
一般而言,預處理器發現程式中的巨集後,會用巨集等價的替換文字進行替換。如果替換的字串中還包含巨集,則繼續替換這些巨集。唯一例外的是雙引號彙總的巨集。因此,下面的語句:
printf
("two: ow\n"
);
列印的是
two: ow
而不是
2
:"consistency is the last refuge of the unimaginative.
- oscar wilde
巨集定義是用巨集名來表示乙個字串,在巨集展開時又以該字串取代巨集名,這只是一種簡單的替換。字串中可以含任何字元,可以是常數,也可以是表示式,預處理程式對它不作任何檢查,如有錯誤,只能在編譯已被巨集展開後的源程式時發現。
巨集定義不是說明或語句,在行末不必加分號,如加上分號則連分號也一起替換。
巨集定義必須寫在函式之外,其作用域為巨集定義命令起到源程式結束。如要終止其作用域可使用#undef
命令。
巨集名在源程式中若用引號括起來,則預處理程式不對其作巨集代換。
巨集定義允許巢狀,在巨集定義的字串中可以使用已經定義的巨集名,在巨集展開時由預處理程式層層代換(一些編譯器不支援這種巢狀功能)。
習慣上巨集名用大寫字母表示,以便於與變數區別。但也允許用小寫字母。
可用巨集定義表示資料型別,使書寫方便。例如:
#define uint unsigned int
在程式中可用uint作變數說明:
uint a, b;
應注意用巨集定義表示資料型別和用typedef定義資料說明符的區別。巨集定義只是簡單的字串代換,是在預處理完成的,而typedef是在編譯時處理的,它不是作簡單的代換,而是對型別說明符重新命名。被命名的識別符號具有型別定義說明的功能。
那麼,何時使用字元常量?對於絕大部分數字常量,應該使用字元常量。如果在算式中用字元常量代替數字,常量名能更清楚地表達該數字的含義。如果是表示陣列大小的數字,用符號常量更容易改變陣列的大小和迴圈次數。如果數字是系統**(如,eof),用符號常量表示的**更容易移植。助記、易更改、可移植,這些都是符號常量很有價值的特性。
參考資料
史蒂芬・普拉達. c primer plus (第6版) 中文版[m]. 人民郵電出版社, 2016.
c語言巨集定義—**↩︎
C語言中const定義常量和巨集常量的區別
2.巨集常量 3.兩者區別 關鍵字const 定義的是變數不是常量,而是去改變乙個變數的儲存類,把該變數所佔的記憶體變為唯讀。這就是變數的值不允許改變的常變數。該常量帶有資料型別。編譯執行的時候起作用存在型別檢查。include const int a 1 const static int b vo...
C語言的巨集之帶引數巨集
c語言允許巨集帶有引數。在巨集定義中的引數稱為形式引數,在巨集呼叫中的引數稱為實際引數,這種巨集外形和作用與函式類似,即類函式巨集。但是它的行為和函式呼叫完全不同。對帶引數的巨集,在呼叫中,不僅要巨集展開,而且要用實參去代換形參。類函式巨集定義的圓括號中可以有乙個或多個引數,隨後這些引數出現在替換體...
C語言的程式設計規範 使用巨集代表邏輯常量
錯誤寫法 if num 0 state 1 program code 正確用法 define send faild 0 define send ok 1 if send ok num state 1 program code 以上 編寫有兩點需要注意 1 在編寫 時盡量少用數字代替邏輯常量,可用有意...