C語言巨集定義使用方法和注意事項

2021-08-20 07:52:18 字數 3002 閱讀 2841

一、總結

1、預處理器直接對巨集進行文字替換

2、巨集使用時的引數不會進行求值和運算

3、預處理器不會對巨集定義進行語法檢查,巨集定義時出現的語法錯誤只能被編譯器檢測

4、巨集定義的效率高於函式呼叫(巨集不占用記憶體,函式占用記憶體)

5、巨集的使用會帶來一定的***

6、#define定義的巨集可以出現在程式的任意位置,#define定義之後的**都可以使用這個巨集

7、#define 表示式的使用類似函式呼叫,但是巨集比函式功能更強大,比函式更容易出錯

8、巨集表示式中不能出現遞迴定義

二、**測試(ubuntu 10  gcc平台)

1、**:

#include #define error  -1

#define path1 "d:/test/test.c"

#define path2 d:/test/test.c

#define path3 d:/test/

//下面這個遞迴是不對的,巨集表示式中不能出現遞迴定義

#define sum(n) (n > 0 ? sum(n - 1) + n : 0)

#define _sum_(a,b) (a) + (b)

#define _min_(a,b) ((a) < (b) ? (a) : (b))

#define _dim_(a) sizeof(a)/sizeof(*a)

//記住用define定義的巨集,預處理之後全都消失

//所以下面這個函式實際是空的,預處理後函式內容都是空的

void def(void)

double area(double r)

int main()

; int s1 = _sum_(a,b);

int s2 = _sum_(a,b)*_sum_(a,b);//這裡預處理好後變成:int s2 = (a) + (b)*(a) + (b); 所以是1 + 2*1 + 2 = 5

int m = _min_(a++,b); //這裡預處理後變成這樣:int m = ((a++) < (b) ? (a++) : (b));所以a執行了兩次++,最後變成3

int d = _dim_(c);

int su = sum(5); //預處理通過,編譯不通過,因為巨集定義不能出現遞迴

printf("a = %d\n",a); //a = 3

printf("s1 = %d\n",s1); //s1 = 3

printf("s2 = %d\n",s2); //s2 = 5

printf("m = %d\n",m); //m = 2

printf("d = %d\n",d); //d = 4

printf("r = %lf\n",r); //r = 78.539815

return 0;

}

我們先看下預處理之後是什麼東西(預處理命令在終端輸入:gcc -e test.c -o test.i  然後找到這個檔案用gedit開啟就行了)

void def(void)

double area(double r)

int main()

; int s1 = (a) + (b);

int s2 = (a) + (b)*(a) + (b);

int m = ((a++) < (b) ? (a++) : (b));

int d = sizeof(c)/sizeof(*c);

int su = (5 > 0 ? sum(5 - 1) + 5 : 0);

printf("a = %d\n",a);

printf("s1 = %d\n",s1);

printf("s2 = %d\n",s2);

printf("m = %d\n",m);

printf("d = %d\n",d);

printf("r = %lf\n",r);

return 0;

}

再看下終端輸出

**裡面都有注釋,講的很清楚,所以不講了

2、**2 (注意:這個**裡面有bug,看看你們能不能發現)

#include #include #define malloc(type,l)  (type *)malloc(sizeof(type) * l)

#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 < m;i++)

#define begin

int main()

這麼看是不是有點複雜,那我們預處理下,在終端輸入gcc -e test.c -o test.i 然後在當前資料夾下面找到這個新生成的test.i,然後雙擊在gedit裡面把它開啟

看出來沒!是不是第1個for後面有個冒號,這是第乙個bug,同樣下面for也是有個冒號,這是第二個bug

那這個bug會導致什麼問題麼?加了冒號,for迴圈什麼都不執行,for迴圈執行完x = 5,下面p[5] = 5 + 1;

但是我們申請內容只申請了5個int型別資料,但是現在賦值到第6個了,所以會導致錯誤,具體什麼現象,你們在終端裡面直接執行就知道了,所以我們把這個bug去掉,然後編譯執行下,看下終端輸出:

參考資料《狄泰軟體c語言高階教程》

巨集定義的注意事項

巨集定義不是函式,它只是不同形式的替換而已,不同於函式的引數巨集定義的引數 暫且稱之為引數 不是作為乙個整體參與計算的,如下例子所示 include using namespace std define fun1 x x x define fun2 x x x int fun3 int x int ...

C語言巨集定義用法注意事項與好處

1.乙個識別符號被巨集定義後,該識別符號便是乙個巨集名。這時,在程式中出現的是巨集名,在該程式被編譯前,先將巨集名用被定義的字串替換,這成為巨集替換,替換後才進行編譯,巨集替換是簡單的替換 2.include define n 2 int main int argc,char argv 這段程式執行...

c語言巨集定義的使用方法

在工程規模較小,不是很複雜,與硬體結合緊密,要求移植性的時候,可採用巨集定義簡化程式設計,增強程式可讀性。當巨集作為常量使用時,c程式設計師習慣在名字中只使用大寫字母。但是並沒有如何將用於其他目的的巨集大寫的統一做法。由於巨集 特別是帶引數的巨集 可能是程式中錯誤的 所以一些程式設計師更喜歡使用大寫...