C語言中,凡是以“#”號開頭的行,都稱為“編譯預處理”命令行。C語言的預處理命令有:#define, #undef, #include, #if, #else, #elif, #endif, #ifdef, #ifndef, #line, #pragma, #error。
(1)不帶參數的宏定義命令行形式如下:
#define 宏名 替換文本
在#define、宏名和宏替換文本之間用空格隔開。例如:
#define SIZE 100
(2)替換文本中可以包含已定義過的宏名,例如:
#define PI 3.14
#define ADDPI (PI + 1)
#define TWO_ADDPI (2 * ADDPI)
(3)當宏定義在一行中寫不下,需要在下一行繼續時,只需在最後一個字符後緊接著加一個反斜線“\”。例如:
#define LEAP_YEAR year % 4 == 0\
&& year % 100 != 0 || year % 400 == 0
如果在“\”前或在下一行的開頭留有空格,則在宏替換時也將加入這些空格。
(4)同一宏名不能重復定義,除非兩個宏定義命令行完全一致。
(5)替換文本不能替換雙引號中與宏名相同的字符串。例如,如果YES是已定義的宏名,則不能用與它相關的替換文本來替換 printf("YES") 中的YES。
(6)替換文本不會替換用戶標識符中的成分。例如,宏名 YES,不會替換標識符 YESORNO 中的 YES。
(7)用作宏定義的標識符通常用大寫字母表示,這並不是語法規定,只是一種習慣,便於與程序中的其他標識符相區別。
(8)C程序中,宏定義的定義位置一般寫在程序的開頭。
(1)帶參數的宏定義命令行形式如下:
#define 宏名( 形參表 ) 替換文本
例如:
#define MU(X, Y) ((X) * (Y))
以上宏定義命令行中,MU(X, Y) 簡稱為“宏”,MU是用戶標識符,稱為宏名。宏名和左括號 "(" 必須緊挨著,它們之間不得留有空格。其中一對圓括號中由若干稱為形參的標識符組成,各形參之間用逗號隔開。“替換文本”中應包含有形參。
(2)和不帶參數的宏定義相同,同一宏名不能重復定義,除非兩個宏定義命令行完全一致。
(3)在調用帶參數的宏名時,一對圓括號必不可少,圓括號中實參的個數應該與形參個數相同,若有多個參數,它們之間用逗號隔開。在預編譯時,編譯預處理程序用“替換文本”來替換宏,並用對應的實參來替換“替換文本”中的形參。
(4)在“替換文本”中的形參和整個表達式應該用括號括起來,例如:
#define MU(x, y) ( (x) * (y) )
(5)宏替換和函數調用有相似之處,但在宏替換中,對參數沒有類型要求。例如,調用 MU,既可以求兩個整型數的乘積,也可求兩個實型數的乘積。而如果是調用函數來求兩個數的乘積,則對不同類型的參數就需要定義不同的函數。
(6)宏替換是在編譯前由預處理程序完成的,因此宏替換不占用運行時間。而函數調用是在程序運行時進行的,在函數調用過程中需要占用處理時間。
可以用 #undef 提前終止宏定義的作用域。例如:
#define PI 3.14
main()
...
#undef PI
...
以上 PI 的作用域從#define PI 3.14 命令行開始,到#undef PI 命令行結束。從#undef 之後 PI 變成無定義,不再代表3.14。
C語言開發程序時,可以把一些宏定義按照功能分別存入不同的文件中。當需要使用某類宏定義時,就無需在程序中重新定義,而只要把這些宏定義所在的文件包含在程序的開頭就可以了。
所謂文件包含,是指在一個文件中去包含另一個文件的全部內容。C語言用#include 命令行來實現文件包含的功能。#include 命令行的形式如下:
#include "文件名"
或
#include <文件名>
預編譯時,預編譯程序將用指定文件中的內容來替換此命令行。a.如果文件名用雙引號括起來,系統先在源程序所在的目錄內查找指定的包含文件,如果找不到,再按照系統指定的標准方式到相關目錄中查找;b.如果文件用尖括號括起來,系統將直接按照系統指定的標准方式到有關目錄查找。
說明:
(1)包含文件的#include 命令行通常應書寫在所用源程序文件的開頭,故包含文件又稱作“頭文件”。頭文件名可以由用戶指定,其後綴不一定用“.h”。
(2)包含文件中,一般包含有一些公用的#define命令行、外部說明或對庫函數的原型說明。例如 stdio.h 就是這樣的頭文件。
(3)當包含文件修改後,對包含文件的源程序必須重新進行編譯連接
(4)一個程序中,允許有任意多個#include命令行。