#define是預處理器處理的單元實體之一;
#define定義的巨集可以出現在程式的任意位置;
#define定義之後的**都可以使用這個巨集。
#define定義的巨集常量可以直接使用;
#define定義的巨集常量本質為字面量(不占用記憶體《唯讀儲存區》—和const常量(變數,佔記憶體)的本質區別)。
下面的巨集定義正確嗎?
#define error -1 //
#define path1 "d:\test.c"
#define path2 d:\test.c
#define path3 d:\test\ //
test.c
編譯執行:
~/will$ gcc -e test.c -o test.i //預編譯沒報錯
int main()
~/will$
~/will$ gcc test.c
test.c: in function 『main』:
test.c:13: error: 『d』 undeclared (first use in this function)
test.c:13: error: (each undeclared identifier is reported only once
test.c:13: error: expected 『,』 or 『;』 before 『:』 token
test.c:13: error: stray 『\』 in program
test.c:14: error: expected 『,』 or 『;』 before 『:』 token
test.c:14: error: stray 『\』 in program
預編譯過程不進行語法語義判斷,表明巨集定義是對的,但是編譯後報錯,不合c語言的語法規範。
const常量本質是變數,佔記憶體;
巨集常量不是變數,不佔記憶體。
#define表示式的使用類似函式呼叫;
#define表示式可以比函式更強大;
#define表示式比函式更容易出錯。
觀察下面**:
#include #define _sum_(a, b) (a) + (b)
#define _min_(a, b) ((a) < (b) ? (a) : (b))
#define _dim_(a) sizeof(a)/sizeof(*a) //比函式更強大的地方在於可以求乙個陣列的大小
int main()
; int s1 = _sum_(a, b);
int s2 = _sum_(a, b) * _sum_(a, b);
int m = _min_(a++, b);
int d = _dim_(c);
printf("s1 = %d\n", s1);
printf("s2 = %d\n", s2);
printf("a = %d\n", a);
printf("m = %d\n", m);
printf("d = %d\n", d);
return 0;
}
先單步編譯:gcc -e test.c -o test.i
得到:
int main()
; int s1 = (a) + (b);
int s2 = (a) + (b) * (a) + (b);
int m = ((a++) < (b) ? (a++) : (b));
int d = sizeof(c)/sizeof(*c);
printf("s1 = %d\n", s1);
printf("s2 = %d\n", s2);
printf("m = %d\n", m);
printf("d = %d\n", d);
return 0;
}
輸出:
s1 = 3
s2 = 5
m = 2
d = 4
預處理器在處理巨集定義時,扮演乙個「傳話筒」的作用。
巨集表示式被預處理器處理,編譯器不知道巨集表示式的存在;
巨集表示式用「實參」完全替代形參,不進行任何運算;
巨集表示式沒有任何的「呼叫」開銷;
巨集表示式不能出現遞迴定義。
#define _sum_(n) ((n>0)?(_sum_(n-1)+n):0)
int s = _sum_(10);
巨集定義的常量或表示式是否有作用域的限制呢?
作用域的概念,針對變數和函式,不針對巨集定義。
為什麼呢?
因為巨集定義是在預編譯階段被處理的,編譯器根本不知道巨集定義的存在。
強大的內建巨集:
巨集 含義 示例
__file__ 被編譯的檔名 file.c
__line__ 當前行號 25
__date___ 編譯時的日期 jan 31 2012
__time__ 編譯時的時間 17:01:02
__stdc__ 編譯時時候遵循標準c規範 1
注意是雙下劃線。
#include #include #define malloc(type, x) (type*)malloc(sizeof(type)*x)
#define free(p) (free(p), p=null)
#define log(s) printf("[%s] %s \n", __date__, __file__, __line__, s)
#define foreach(i, m) for(i=0; i執行結果:
~/will$ ./a.out
[may 1 2018] begin to run main code... 01
234[may 1 2018] end
小結:
預處理器直接對巨集進行文字替換;
巨集使用時的引數不會進行求值和運算;
預處理器不會對巨集定義進行語法檢查;
巨集定義時出現的語法錯誤只能被編譯器檢測;
巨集定義的效率高於函式呼叫;
巨集的使用會帶來一定的***。
C 21 巨集定義與使用分析
test.c define error 1 define path1 d test test.c define path2 d test test.c define path3 d test 成為接續符 test.c int main test.i 1 test.c 1 1 1 test.c int...
C 21 巨集定義與使用分析
define是預處理處理的單元實體之一。定義的巨集可以出現在程式的任意位置,定義之後 都可以使用這個巨集。預處理器不會進行語法分析的 直接進行文字替換 後面的編譯器才進行語法分析,這個過程很容易產生歧義錯誤。define 定義的巨集常量可以直接使用 define 定義的巨集常量本質為字面量 defi...
C語言中巨集定義與使用分析
事物的難度遠遠低於對事物的恐懼!這個章節我們來談一談c語言中的巨集定義與使用分析,相信每個學過c的都知道,在c中,巨集具有如下三個特性 define是預處理器處理的單元實體之一 define定義的巨集可以出現在 程式的任意位置 define定義之後的 都可以使用這個巨集 而在c語言中,我們常常用 d...