C語(yǔ)言基本概念宏定義中的#和##教程
#和##是宏定義中常用的兩個(gè)預(yù)處理運(yùn)算符
其中#用于記號(hào)串化,##用于記號(hào)黏結(jié),下面分別介紹它們。
1. 記號(hào)串化(#)
記號(hào)串化可以將函數(shù)式宏定義中的實(shí)參轉(zhuǎn)換為字符串。在函數(shù)式宏定義中,如果替換列表中有“#”,則其后的預(yù)處理記號(hào)必須是當(dāng)前宏的形參。在預(yù)處理期間,“#”連同它后面的形參一起被實(shí)參取代。例如
#include <stdio.h>
#define PSQR(x) printf("The square of " #x " is %d.\n",((x)*(x)))
int main(void)
{
int y = 5;
PSQR(y);
PSQR(2 + 4);
PSQR( 3 * 2 );
return 0;
}程序運(yùn)行結(jié)果如下:

第1次調(diào)用宏時(shí),用"y"替換#x。第2次調(diào)用宏時(shí),用"2 + 4"替換#x。第3次調(diào)用宏時(shí),用"3 * 2"替換#x。
ANSI C字符串的串聯(lián)特性將這些字符串與printf()語(yǔ)句的其他字符串組合,生成最終的字符串。例如,第1次調(diào)用變成:
printf("The square of " "y" " is %d.\n",((y)*(y)));
然后,字符串串聯(lián)功能將這3個(gè)相鄰的字符串組合成一個(gè)字符串:
"The square of y is %d.\n"
如果傳入的實(shí)參中間有空白,則不管有多少,都被轉(zhuǎn)換為一個(gè)空格,參數(shù)開(kāi)頭和末尾的空白都被刪除。例如第3次調(diào)用宏時(shí),實(shí)參“3 * 2 ”轉(zhuǎn)換為“3 * 2”。
2. 記號(hào)黏結(jié)(##)
與#運(yùn)算符類似,##運(yùn)算符可用于函數(shù)式宏的替換部分,它把兩個(gè)記號(hào)組合成一個(gè)記號(hào)。例如,可以這樣定義函數(shù)式宏:
#define XNAME(n) x ## n
然后,展開(kāi)宏XNAME(4)為x4。
記號(hào)黏結(jié)的作用是將幾個(gè)預(yù)處理記號(hào)合并為一個(gè)。在一個(gè)函數(shù)式宏定義中,如果一個(gè)預(yù)處理記號(hào)的前面或者后面有"##",則該記號(hào)將與它前面或者后面的記號(hào)合并,如果該預(yù)處理記號(hào)是宏的形參,則用實(shí)參執(zhí)行合并。例如:
#define F(x, y, z) x##y##r char F(a, b, c);
第2行的宏調(diào)用,其擴(kuò)展之后如下:
char abr;
需要注意的是,在函數(shù)式宏定義中,“##”不能位于替換列表的開(kāi)頭和結(jié)尾。
#include <stdio.h>
#define XNAME(n) x ## n
#define PRINT_XN(n) printf("x" #n " = %d\n", x ## n);
int main(void)
{
int XNAME(1) = 14; // 轉(zhuǎn)換為 x1 = 14;
int XNAME(2) = 20; // 轉(zhuǎn)換為 int x2 = 20;
int x3 = 30;
PRINT_XN(1); // 轉(zhuǎn)換為 printf("x1 = %d\n", x1);
PRINT_XN(2); // 轉(zhuǎn)換為 printf("x2 = %d\n", x2);
PRINT_XN(3); // 轉(zhuǎn)換為 printf("x3 = %d\n", x3);
return 0;
}程序運(yùn)行結(jié)果如下。

3. 分析下列程序運(yùn)行結(jié)果
#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
int main()
{
printf("h(f(1,2))展開(kāi)為:%s\n",h(f(1,2)));
printf("g(f(1,2))展開(kāi)為:%s\n",g(f(1,2)));
return 0;
}析:
宏展開(kāi)順序大致可以歸結(jié)為:
第一步:首先用實(shí)參代替形參,將實(shí)參代入宏文本中
第二步:如果實(shí)參也是宏,則展開(kāi)實(shí)參
第三步:最后繼續(xù)處理宏替換后的宏文本,如果仍包含宏,則繼續(xù)展開(kāi)
注意:如果在第二步,實(shí)參代入宏文本后,實(shí)參之前或之后遇到#或##,實(shí)參不再展開(kāi)
根據(jù)以上宏展開(kāi)步驟分析第8行的宏調(diào)用h(f(1,2)),其展開(kāi)步驟為:
h(f(1,2))-->g(f(1,2))-->g(1##2)-->g(12)-->"12"
第9行的宏調(diào)用g(f(1,2)),其展開(kāi)步驟為:
g(f(1,2))-->#f(1,2)-->"f(1,2)"
上面程序運(yùn)行結(jié)果如下。

以上就是C語(yǔ)言基本概念宏定義中的#和##教程的詳細(xì)內(nèi)容,更多關(guān)于C語(yǔ)言宏定義#和##的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)數(shù)獨(dú)程序的示例代碼
數(shù)獨(dú)是源自瑞士的一種數(shù)學(xué)游戲。是一種運(yùn)用紙、筆進(jìn)行演算的邏輯游戲。本文將利用C語(yǔ)言實(shí)現(xiàn)數(shù)獨(dú)程序,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-03-03
C語(yǔ)言實(shí)現(xiàn)歌手大獎(jiǎng)賽計(jì)分程序
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)歌手大獎(jiǎng)賽計(jì)分程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-03-03
C++開(kāi)發(fā)的Redis數(shù)據(jù)導(dǎo)入工具優(yōu)化
這篇文章主要介紹了C++開(kāi)發(fā)的Redis數(shù)據(jù)導(dǎo)入工具優(yōu)化方法的相關(guān)資料,需要的朋友可以參考下2015-07-07
Qt圖形圖像開(kāi)發(fā)之曲線圖表模塊QChart庫(kù)讀取/設(shè)置X軸的顯示區(qū)間
這篇文章主要介紹了Qt圖形圖像開(kāi)發(fā)之曲線圖表模塊QChart庫(kù)讀取/設(shè)置X軸的顯示區(qū)間,需要的朋友可以參考下2020-03-03
C語(yǔ)言實(shí)現(xiàn)數(shù)字炸彈小游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)數(shù)字炸彈小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11
整型數(shù)據(jù)在內(nèi)存中存儲(chǔ)方式的講解
今天小編就為大家分享一篇關(guān)于整型數(shù)據(jù)在內(nèi)存中存儲(chǔ)方式的講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-02-02

