C語言中,可以用 #define 定義一個識別符號來表示一個常數。其特點是:
定義的識別符號不佔記憶體,只是一個臨時的符號,預編譯後這個符號就不存在了。
預編譯又叫
預處理。
預編譯不是編譯,而是編譯前的處理。這個操作是在正式編譯之前由系統自動完成的。
用 #define 定義識別符號的一般形式為:
#define 識別符號 常數 //注意, 最後沒有分號
#define 和 #include 一樣,也是以“#”開頭的。凡是以“#”開頭的均為
預處理指令,#define也不例外。
#define又稱
宏定義,識別符號為所定義的宏名,簡稱
宏。識別符號的命名規則與前面講的變數的命名規則是一樣的。
#define 的功能是將識別符號定義為其後的常數。一經定義,程式中就可以直接用識別符號來表示這個常數。是不是與定義變數類似?但是要區分開!
變數名表示的是一個變數,但宏名表示的是一個常數。可以給變數賦值,但絕不能給常數賦值。
宏所表示的常數可以是數位、字元、字串、表示式。其中最常用的是數位。
那麼,程式中什麼時候會使用宏定義呢?用宏定義有什麼好處呢?我們直接寫數位不行嗎?為什麼要用一個識別符號表示數位呢?
宏定義最大的好處是“方便程式的修改”。使用宏定義可以用宏代替一個在程式中經常使用的常數。注意,是“經常”使用的。這樣,當需要改變這個常數的值時,就不需要對整個程式一個一個進行修改,只需修改宏定義中的常數即可。且當常數比較長時,使用宏就可以用較短的有意義的識別符號來代替它,這樣程式設計的時候就會更方便,不容易出錯。因此,宏定義的優點就是方便和易於維護。
那麼程式在預編譯的時候是怎麼處理宏定義的呢?或者說是怎麼處理預處理指令的呢?
其實預編譯所執行的操作就是簡單的“文字”替換。對宏定義而言,預編譯的時候會將程式中所有出現“識別符號”的地方全部用這個“常數”替換,稱為“宏替換”或“宏展開”。替換完了之後再進行正式的編譯。所以說當單擊“編譯”的時候實際上是執行了兩個操作,即先預編譯,然後才正式編譯。#include<stdio.h>也是這樣的,即在預處理的時候先單純地用標頭檔案stdio.h中所有的“文字”內容替換程式中#include<stdio.h>這一行,然後再進行正式編譯。
需要注意的是,預處理指令不是語句,所以後面不能加分號。這是很多新手經常犯的錯誤。#include 後面也沒有加分號。
宏定義 #define 一般都寫在函數外面,與 #include 寫在一起。當然,寫在函數裡面也沒有語法錯誤,但通常不那麼寫。#define 的作用域為自 #define 那一行起到源程式結束。如果要終止其作用域可以使用 #undef 命令,格式為:
#undef 識別符號
undef 後面的識別符號表示你所要終止的宏。比如前面在程式開頭用 define 定義了一個宏 M,它原本的作用範圍是一直到程式結束,但如果現在在程式中某個位置加了一句:
#undef M
那麼這個宏的作用範圍到此就結束了。#undef 用得不多,但大家要了解。
為了將識別符號與變數名區別開來,習慣上識別符號全部用大寫字母表示。宏定義用得最多的地方是在陣列中用於指定陣列的長度。下面來寫一個程式:
# include <stdio.h>
# define NUM 5
int main(void)
{
int i, j = NUM;
int a[NUM] = {0};
printf("請輸入%d個數:", j);
for (i=0; i<NUM; ++i)
{
scanf("%d", &a[i] );
}
for (i=0; i<NUM; ++i)
{
printf("%dx20", a[i]);
}
printf("n");
return 0;
}
輸出結果是:
請輸入5個數:5 4 3 2 1
5 4 3 2 1
NUM 是定義的宏,它表示的是其後的常數(而不是變數)。此外,程式中用雙引號括起來的宏在預處理的時候是不會被宏替換的。因為在 C 語言中,用雙引號括起來表示的是字串。下面再寫一個程式看一下:
# include <stdio.h>
# define PI 3.14159
int main(void)
{
double r, s;
printf("請輸入圓的半徑:");
scanf("%lf", &r); //scanf中, double只能用%lf
s = PI * r * r;
printf("s=PI*r^2 = %.6fn", s); //PI不會被宏替換
return 0;
}
輸出結果是:
請輸入圓的半徑:1
s=PI*r^2 = 3.141590