參數
#define GPEBLT_FUNCNAME(basename) (SCODE (GPE::*)(struct GPEBltParms *))&GPE::##basename
在#define中,標準只定義了#和##兩種操作。#用來把參數轉換成字元串,##則用來連線前後兩個參數,把它們變成一個字元串。
#include<stdio.h>#define paster(n) printf("token"#n"=%d\n",token##n)int main(void){int token9=10;paster(9);return 0;}
輸出為:token 9 = 10
作用
被定義為“宏”的標識符稱為“宏名”。在編譯預處理時,對程式中所有出現的“宏名”,都用
宏定義中的字元串去代換,這稱為“宏代換”或“宏展開”。宏定義是由
源程式中的宏定義命令完成的。宏代換是由預處理程式自動完成的。
宏定義的作用範圍僅限於當前檔案,即file1.c中定義 #define PI 3.14,在file2.c中該宏定義不起作用;通過將#define PI 3.14定義在common.h中,file1.c和file2.c分別#include "common.h"的方式,該宏定義在file1.c和file2.c中都起作用。
在C或C++語言中,“宏”分為有參數和無參數兩種。
宏定義優點
(1) 方便程式的修改
使用簡單
宏定義可用宏代替一個在程式中經常使用的
常量,這樣在將該常量改變時,不用對整個程式進行修改,只修改宏定義的字元串即可,而且當常量比較長時, 我們可以用較短的有意義的
標識符來寫程式,這樣更方便一些。我們所說的常量改變不是在程式運行期間改變,而是在編程期間的修改,舉一個大家比較熟悉的例 子,圓周率π是在數學上常用的一個值,有時我們會用3.14來表示,有時也會用3.1415926等,這要看計算所需要的精度,如果我們編制的一個程式中 要多次使用它,那么需要確定一個數值,在本次運行中不改變,但也許後來發現程式所表現的精度有變化,需要改變它的值, 這就需要修改程式中所有的相關數值,這會給我們帶來一定的不便,但如果使用宏定義,使用一個
標識符來代替,則在修改時只修改宏定義即可,還可以減少輸入 3.1415926這樣長的數值多次的情況,我們可以如此定義 #define pi 3.1415926,既減少了輸入又便於修改,何樂而不為呢?
(2) 提高程式的運行效率
使用帶參數的宏定義可完成
函式調用的功能,又能減少系統開銷,提高運行效率。正如C語言中所講,函式的使用可以使程式更加模組化,便於組織,而且可重複利用,但在發生函式調用時,需要保留調用函式的現場,以便子函式執行結束後能返回繼續執行,同樣在子函式執行完後要恢復調用函式的現場,這都需要一定的時間,如果子函式執行的操作比較多,這種轉換時間開銷可以忽略,但如果子函式完成的功能比較少,甚至於只完成一點操作,如一個乘法語句的操作,則這部分轉換開銷就相對較大了,但使用帶參數的
宏定義就不會出現這個問 題,因為它是在預處理階段即進行了宏展開,在執行時不需要轉換,即在當地執行。宏定義可完成簡單的操作,但複雜的操作還是要由
函式調用來完成,而且宏定義所占用的
目標代碼空間相對較大。所以在使用時要依據具體情況來決定是否使用宏定義。
無參宏定義
無參宏定義的一般形式為:#define
標識符 字元串
其中的“#”表示這是一條
預處理命令。凡是以“#”開頭的均為預處理命令。“define”為
宏定義命令。“標識符”為所定義的宏名。“字元串”可以是常數、
表達式、格式串等。
例如: #define M (a+b) 它的作用是指定標識符M來代替表達式(a+b)。在編寫
源程式時,所有的(a+b)都可由M代替,而對源程式作編譯時,將先由預處理程式進行宏代換,即用(a+b)表達式去置換所有的宏名M,然後再進行編譯。
程式1:
#include<stdio.h>#define M (a+b)int main(void){int s,a,b;printf("inputnumbera&b:");scanf("%d%d",&a,&b);s = M*M;printf("s=%d\n",s);}
上例程式中首先進行
宏定義,定義M來替代
表達式(a+b),在 s= M * M 中作了宏調用。在預處理時經宏展開後該語句變為: S=(a+b)*(a+b) 但要注意的是,在宏定義中表達式(a+b)兩邊的括弧不能少。否則會發生錯誤。 如當作以下定義後:#define M (a)+(b) 在宏展開時將得到下述語句:S= (a)+(b)*(a)+(b)
對於宏定義還要說明以下幾點:
1.宏定義是用宏名來表示一個字元串,在宏展開時又以該字元串取代宏名,這只是一種簡單的代換,字元串中可以含任何字元,可以是常數,也可以是表達式,預處理程式對它不作任何檢查。如有錯誤,只能在編譯已被宏展開後的源程式時發現。
2.
宏定義不是說明或語句,在行末不必加分號,如加上分號則連分號也一起置換。
3.宏定義其
作用域為宏定義命令起到源程式結束。如要終止其作用域可使用#undef命令。 (有關#undef 請查閱其他資料)
帶參宏定義
帶參宏定義的一般形式為: #define 宏名(形參表) 字元串
在字元串中含有各個形參。 帶參宏調用的一般形式為: 宏名(形參表)
例如:
#define M(y) ((y)*(y)+3*(y))/*宏定義*/k=M(5);/*宏調用*/
在宏調用時,用
實參5去代替
形參y,經預處理宏展開後的語句為: k=5*5+3*5
程式2:
#include<stdio.h>#define MAX(a,b) ((a>b)?(a):(b))int main(int argc,char *argv[]){ int x,y,max; printf("input two numbers:\n"); scanf("%d%d",&x,&y); max=MAX(x,y); printf("max=%d\n",max); return 0;}
上例程式的第一行進行帶參
宏定義,用宏名MAX表示條件表達式 (a>b)?a:b ,
形參a,b均出現在條件表達式中。程式中 max=MAX(x,y) 為宏調用,
實參x,y,將代換形參a,b。宏展開後該語句為: max=(x>y)?x:y; 用於計算x,y中的大數。
頭檔案(.h)可以被頭檔案或C檔案包含;重複包含(重複定義)由於頭檔案包含可以嵌套,那么C檔案就有可能包含多次同一個頭檔案,就可能出現重複定義的問題的。 通過條件編譯開關來避免重複包含(重複定義)
例如
#ifndef__headerfileXXX__#define__headerfileXXX__//檔案內容#endif
詳見百科#typedef(相似)
PHP用法
define() 函式定義一個常量。
在設定以後,常量的值無法更改
常量名不需要開頭的美元符號 ($)
例子
例子 1
定義一個大小寫敏感的常量:
<?phpdefine("GREETING","Helloworld!");echoconstant("GREETING");?>
輸出:
Hello world!
例子 2
<?phpdefine("GREETING","Helloworld!",TRUE);echoconstant("greeting");?>
輸出:
Hello world!