http://c.biancheng.net/view/187.html
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("%d\x20", 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 = %.6f\n", s); //PI不會被宏替換
return 0;
}
輸出結果是:
請輸入圓的半徑:1
s=PI*r^2 = 3.141590