国产成人精品三级麻豆,色综合天天综合高清网,亚洲精品夜夜夜,国产成人综合在线女婷五月99播放,色婷婷色综合激情国产日韩

當(dāng)前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > C語言中的宏

C語言中的宏 時間:2018-09-20      來源:未知

宏定義是我們C語言學(xué)習(xí)中非常重要的內(nèi)容。一些基礎(chǔ)的用法大家都比較清楚了,我們簡單總結(jié)一下。

1.宏定義的格式為:#define 標(biāo)識符 字符串。

2.宏定義屬于預(yù)處理命令,在編譯過程中的預(yù)處理階段處理。

3.宏定義只是單純的替換,所以當(dāng)被替換內(nèi)容涉及運算等的時候好加上括號()。

4.宏定義的標(biāo)示符一般用大寫。

5.宏定義的標(biāo)示符為常量標(biāo)示符,即不可再賦值。

6.宏定義末尾不加分號。

以上說的是宏定義的近本用法,可以帶來很多好處。比如讓我們的標(biāo)示符有意義,讓我們的代碼修改更方便,可以替代在代碼中常用的字符串縮短代碼等。其實在宏定義中,我們也可以像一個“函數(shù)”一樣實現(xiàn)一個的功能,這種用法叫函數(shù)宏,函數(shù)宏在我們對宏定義的使用中更加的常江,下面我們從五個方面來了解下函數(shù)宏的使用。

1.函數(shù)宏的書寫

#defineMAX(a,b)((a)(b)?(a):(b)),這就是一個簡單的函數(shù)宏,我們同樣可以傳遞參數(shù),實現(xiàn)功能。但是在書寫上注意兩點MAX和左“(”之間沒有空格,因為宏定義把標(biāo)示符后的第一個空格會認(rèn)為是標(biāo)示符與字符串的分割。當(dāng)然我們在寫宏的時候有時候會寫多行,這樣我們一般用“\”進行分割。

2.加括號

我們說到宏只是簡單的替換,即使是函數(shù)宏也是這樣的,所以為了避免一些優(yōu)先級的錯誤不要忘記加括號。

3.宏的副作用

這也是函數(shù)宏和函數(shù)不同的地方。比如上邊的例子 #define MAX(a,b) ((a)>(b)?(a):(b))我們傳入的參數(shù)是++a和++b。很顯然如果使用函數(shù)實現(xiàn)這個功能的話a和b均自加一次,但是如果用宏實現(xiàn)替換后就變成((++a)>(++b)?(++a):(++b)),很明顯,這與函數(shù)就完全不同了。

4.do{}while(0)結(jié)構(gòu)

例如:

#define DELETE_POINTER(p) \

do \

{ \

if(NULL != p) \

delete p; \

p = NULL; \

}while(0)

這種結(jié)構(gòu)在函數(shù)宏里非常常見,它不僅可以在調(diào)用后加分號保持代碼的格式一致性,還可以避免一些復(fù)雜的宏定義產(chǎn)生的錯誤。當(dāng)然,每行后面不要忘了也是需要”\”的。

5.函數(shù)宏中的#和##運算符

在函數(shù)宏中#可以實現(xiàn)由函數(shù)宏實參生成字符串常量,##實現(xiàn)了由函數(shù)宏實參生成標(biāo)識符的一部分。(前者用于拼接字符串后者用于拼接標(biāo)示符)看一下下邊的示例:

#

假如希望在字符串中包含宏參數(shù),ANSIC允許這樣作,在類函數(shù)宏的替換部分,#符號用作一個預(yù)處理運算符,它可以把語言符號轉(zhuǎn)化程字符串。例如,如果x是一個宏參量,那么#x可以把參數(shù)名轉(zhuǎn)化成相應(yīng)的字符串。該過程稱為字符串化(stringizing)。

#incldue

#define PSQR(x) printf("the square of" #x "is %d.\n",(x)*(x))

int main(void)

{

int y =4;

PSQR(y);

PSQR(2+4);

return 0;

}

輸出結(jié)果:

the square of y is 16.

the square of 2+4 is 36.

第一次調(diào)用宏時使用“y”代替#x;第二次調(diào)用時用“2+4"代#x。

##

##運算符可以使用類函數(shù)宏的替換部分。另外,##還可以用于類對象宏的替換部分。這個運算符把兩個語言符號組合成單個語言符號。例如:

#define XNAME(n) x##n

這樣宏調(diào)用:

XNAME(4)

展開后:x4

程序:

#include

#define XNAME(n) x##n

#define PXN(n) printf("x"#n" = %d\n",x##n)

int main(void)

{

int XNAME(1)=12;//int x1=12;

PXN(1);//printf("x1 = %d\n", x1);

return 0;

}

那么說了這么多,大家一定有疑問,函數(shù)宏和函數(shù)的區(qū)別又有什么呢?我們把上面第一條的例子用函數(shù)來實現(xiàn):

int max( int a, int b)

{

return (a > b a : b)

}

如果這段代碼要頻繁使用,讓我們選擇用函數(shù)宏或者用函數(shù)來實現(xiàn)。很顯然,我們不會選擇用函數(shù)來完成這個任務(wù),原因有兩個:首先,函數(shù)調(diào)用會帶來額外的開銷,它需要開辟一片?臻g,記錄返回地址,將形參壓棧,從函數(shù)返回還要釋放堆棧。這種開銷不僅會降低代碼效率,而且代碼量也會大大增加,而使用宏定義則在代碼規(guī)模和速度方面都比函數(shù)更勝一籌;其次,函數(shù)的參數(shù)必須被聲明為一種特定的類型,所以它只能在類型合適的表達式上使用,我們?nèi)绻容^兩個浮點型的大小,就不得不再寫一個專門針對浮點型的比較函數(shù)。反之,上面的那個宏定義可以用于整形、長整形、單浮點型、雙浮點型以及其他任何可以用“>”操作符比較值大小的類型,也就是說,宏是與類型無關(guān)的。和使用函數(shù)相比,使用宏的不利之處在于每次使用宏時,一份宏定義代碼的拷貝都會插入到程序中。除非宏非常短,否則使用宏會大幅度增加程序的長度。還有一些任務(wù)根本無法用函數(shù)實現(xiàn),但是用宏定義卻很好實現(xiàn)。比如參數(shù)類型沒法作為參數(shù)傳遞給函數(shù),但是可以把參數(shù)類型傳遞給帶參的宏。

看下面的例子:

#define MALLOC(n, type) \

( (type *) malloc((n)* sizeof(type)))

利用這個宏,我們就可以為任何類型分配一段我們指定的空間大小,并返回指向這段空間的指針。我們可以觀察一下這個宏確切的工作過程:

int *ptr;

ptr = MALLOC ( 5, int );

將這宏展開以后的結(jié)果:

ptr = (int *) malloc ( (5) * sizeof(int) );

這個例子是宏定義的經(jīng)典應(yīng)用之一,完成了函數(shù)不能完成的功能。

把類型作為函數(shù)宏參數(shù)是C語言實現(xiàn)泛型的一種手段,這也是函數(shù)宏常用的場合之一。在后續(xù)出現(xiàn)的編程語言入C++中把這種需求作為一種新的語法特性(模板)加以實現(xiàn)。

我們主要介紹了函數(shù)宏的用法,熟練的掌握還需要更多的練習(xí),希望在以后代碼編程過程中可以將函數(shù)宏融入我們的代碼,使我們的代碼水平不斷提高。

上一篇:印制電路板(PCB)設(shè)計原則和抗干擾措施

下一篇:Ipv6 煙霧傳感器實驗

熱點文章推薦
華清學(xué)員就業(yè)榜單
高薪學(xué)員經(jīng)驗分享
熱點新聞推薦
前臺專線:010-82525158 企業(yè)培訓(xùn)洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權(quán)所有 ,京ICP備16055225號-5,京公海網(wǎng)安備11010802025203號

回到頂部