C語言高階 21 巨集定義與使用分析

2021-08-20 03:31:24 字數 3509 閱讀 7996

#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...