define宏定义中的#,##,@#及\符号
define宏定義中的#,##,@#及\符號
在#define中,標準只定義了#和##兩種操作。#用來把參數轉換成字符串,##則用來連接兩個前后兩個參數,把它們變成一個字符串。?
1、#?(stringizing)字符串化操作符。其作用是:將宏定義中的傳入參數名轉換成用一對雙引號括起來參數名字符串。其只能用于有傳入參數的宏定義中,且必須置于宏定義體中的參數名前。
如:
#define?example(instr)?printf("the?input?string?is:\t%s\n",#instr)
#define?example1(instr)?#instr
當使用該宏定義時:
example(abc);?在編譯時將會展開成:printf("the?input?string?is:\t%s\n","abc");
string?str=example1(abc);?將會展成:string?str="abc";
注意:
對空格的處理
a。忽略傳入參數名前面和后面的空格。
???如:str=example1(???abc?);?將會被擴展成?str="abc";
b.當傳入參數名間存在空格時,編譯器將會自動連接各個子字符串,用每個子字符串中只以一個空格連接,忽略其中多余一個的空格。
???如:str=exapme(?abc????def);?將會被擴展成?str="abc?def";
?
2、##?(token-pasting)符號連接操作符
宏定義中:參數名,即為形參,如#define?sum(a,b)?(a+b);中a和b均為某一參數的代表符號,即形式參數。
而##的作用則是將宏定義的多個形參成一個實際參數名。
如:
#define?exampleNum(n)?num##n
int?num9=9;
使用:
int?num=exampleNum(9);?將會擴展成?int?num=num9;
注意:
1.當用##連接形參時,##前后的空格可有可無。
如:#define?exampleNum(n)?num?##?n?相當于?#define?exampleNum(n)?num##n
2.連接后的實際參數名,必須為實際存在的參數名或是編譯器已知的宏定義
?
//?preprocessor_token_pasting.cpp
#include?<stdio.h>
#define?paster(?n?)?printf_s(?"token"?#n?"?=?%d",?token##n?)
int?token9?=?9;
?
int?main()
{
???paster(9);
}
運行結果:
token9?=?9
?
3、@#?(charizing)字符化操作符。
只能用于有傳入參數的宏定義中,且必須置于宏定義體中的參數名前。作用是將傳的單字符參數名轉換成字符,以一對單引用括起來。
#define?makechar(x)??#@x
a?=?makechar(b);
展開后變成了:
a=?'b';
?
4、\?行繼續操作符
當定義的宏不能用一行表達完整時,可以用"\"表示下一行繼續此宏的定義。
注意:換行不能切斷單詞,只能在空格的地方進行。
?
?
?
宏定義的特殊符號#?##?-?[C++]
?
1.?利用宏參數創建字符串:#?運算符
?
????在類函數宏(function-like?macro)的替換部分中,“#”符號用作一個預處理運算符,它可以把語言符號(token)轉化為字符串。例如,如果?x?是一個宏參量,那么?#x?可以把參數名轉化為相應的字符串。該過程稱為字符串化。
?
????說明:類函數宏就是帶參數的宏。類函數宏的定義中,用圓括號括起來一個或多個參數,隨后這些參數出現在替換部分。
#include?<stdio.h>????
#define?PSQR(x)?printf("The?square?of?"?#x?"?is?%d.?\r\n",?(x)?*?(x))????
????
int?main(void)???
{???
????int?y?=?5;????
???????
????PSQR(y);???
????PSQR(2?+?4);????
????
????return?0;????
}???
????
//?輸出:???
The?square?of?y?is?25.?????//?用?"y"?代替?#x????
The?square?of?2?+?4?is?36.?//?用?"2?+?4"?代替?#x??
#include?<stdio.h>?
#define?PSQR(x)?printf("The?square?of?"?#x?"?is?%d.?\r\n",?(x)?*?(x))?
?
int?main(void)
{
????int?y?=?5;?
????
????PSQR(y);
????PSQR(2?+?4);?
?
????return?0;?
}
?
//?輸出:
The?square?of?y?is?25.?????//?用?"y"?代替?#x?
The?square?of?2?+?4?is?36.?//?用?"2?+?4"?代替?#x
#define?STRING2(x)?#x???
#define?STRING(x)?STRING2(x)???
????
#define?WQ?wangqi????
????
#pragma?message(STRING2(WQ))?//?WQ(字符串)???
#pragma?message(STRING(WQ))??//?wangqi(字符串)??
#define?STRING2(x)?#x
#define?STRING(x)?STRING2(x)
?
#define?WQ?wangqi?
?
#pragma?message(STRING2(WQ))?//?WQ(字符串)
#pragma?message(STRING(WQ))??//?wangqi(字符串)?
2.?預處理器的粘合劑:##?運算符
?
????和?#?運算符一樣,##?運算符可以用于類函數宏的替換部分。另外,##?運算符還可用于類對象宏(object-like?macro)的替換部分。這個運算符把兩個語言符號組合成單個語言符號。例如,可以定義如下宏:
#define?XNAME(n)?x?##?n??
#define?XNAME(n)?x?##?n
????宏調用?XNAME(4)?會展開成?x4?。
?
????說明:類對象宏就是用來代表值的宏。如,#define?PI?3.141593?中的PI。
#include?<stdio.h>????
#define?XNAME(n)?x?##?n????
#define?PRINT_XN(n)?printf("x"?#n?"?=?%d\r\n",?x?##?n);????
????
int?main(void)???
{???
????int?XNAME(1)?=?14;?//?變為?int?x1?=?14;????
????int?XNAME(2)?=?20;?//?變為?int?x2?=?20;????
????PRINT_XN(1)????????//?變為?printf("x1?=?%d\r\n",?x1);????
????PRINT_XN(2)????????//?變為?printf("x2?=?%d\r\n",?x2);????
????
????return?0;????
}???
????
//?輸出:???
x1?=?14????
x2?=?20???
#include?<stdio.h>?
#define?XNAME(n)?x?##?n?
#define?PRINT_XN(n)?printf("x"?#n?"?=?%d\r\n",?x?##?n);?
?
int?main(void)
{
????int?XNAME(1)?=?14;?//?變為?int?x1?=?14;?
????int?XNAME(2)?=?20;?//?變為?int?x2?=?20;?
????PRINT_XN(1)????????//?變為?printf("x1?=?%d\r\n",?x1);?
????PRINT_XN(2)????????//?變為?printf("x2?=?%d\r\n",?x2);?
?
????return?0;?
}
?
//?輸出:
x1?=?14?
x2?=?20?
#define?__T(x)??????L?##?x???
#define?_T(x)???????__T(x)???
#define?_TEXT(x)????__T(x)???
????????
#define?WQ?"wangqi"????
????????
#pragma?message(__T(WQ))?//?LWQ?(標識符)???
wcout?<<?_T(WQ);?????????//?wangqi(寬字節字符串)??
#define?__T(x)??????L?##?x
#define?_T(x)???????__T(x)
#define?_TEXT(x)????__T(x)
?????
#define?WQ?"wangqi"?
?????
#pragma?message(__T(WQ))?//?LWQ?(標識符)
wcout?<<?_T(WQ);?????????//?wangqi(寬字節字符串)?
3.?語言符號?
?
????從技術方面看,系統把宏的主體當作語言符號(token)類型字符串,而不是字符型字符串。C?預處理器中的語言符號是宏定義主體中的單獨的“詞(word)”。用空白字符把這些詞分開。例如:
#define?FOUR?2*2??
#define?FOUR?2*2
????這個定義中有一個語言符號:即序列?2*2?。但是:
#define?SIX?2?*?3??
#define?SIX?2?*?3
????這個定義中有三個語言符號:2、*?和?3?。
?
????在處理主體中的多個空格時,字符型字符串和語言符號型字符串采用不同方法。考慮下面的定義:
#define?EIGHT?4????*????8??
#define?EIGHT?4????*????8
????把主體解釋為字符型字符串時,預處理器用?4????*????8?替換?EIGHT?。也就是說,額外的空格也當作替換文本的一部分。但是,當把主體解釋為語言符號類型時,預處理器用由單個空格分隔的三個語言符號,即?4?*?8?來替換?EIGHT?。?換句話說,用字符型字符串的觀點看,空格也是主體的一部分;而用語言符號字符串的觀點看,空格只是分隔主體中語言符號的符號。在實際應用中,有些?C?編譯器把宏主體當作字符串而非語言符號。在比這個實例更復雜的情況下,字符與語言符號之間的差異才有實際意義。
?
????順便提一下,C?編譯器處理語言符號的方式比預處理器的處理方式更加復雜。編譯器能理解?C?的規則,不需要用空格來分隔語言符號。例如,C?編譯器把?2*2?當作三個語言符號。原因是?C?編譯器認為每個?2?都是一個常量,而?*?是一個運算符。
?
轉載于:https://www.cnblogs.com/TTTTT/p/3701871.html
總結
以上是生活随笔為你收集整理的define宏定义中的#,##,@#及\符号的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 循环查询sql带逗号(,)分隔的数据 以
- 下一篇: Unity Game Starter K