宏定义两个数比大小c语言,宏定义中出现两个#是如何个用法(2)

本文深入探讨了C/C++中的宏定义技巧,包括如何使用#与##操作符实现字符串化及Token拼接,展示了宏定义在代码中的实际应用案例。

C/C++ code#include

using namespace std;

#define X "abc"##"def" // 将abc和def连起来

int main(void)

{

cout << X << endl; // 输出abcdef

return 0;

}

------解决方案--------------------

#的功能是将其后面的宏参数进行字符串化操作

##用来将多个Token连接为一个Token

------解决方案--------------------

#与##在宏定义中的--宏展开

#include

#define f(a,b) a##b

#define g(a) #a

#define h(a) g(a)

int main()

{

printf("%s\n", h(f(1,2))); // 12

printf("%s\n", g(f(1,2))); // f(1,2)

return 0;

}

宏展开时:

如果宏定义以#开头,不展开参数,直接替换。

故g(f(1,2))--->#f(1,2)--->"f(1,2)";

如果宏定义不以#开头,展开参数,直接替换,由外层向里层,如果碰到的是#开头的宏,不继续往里层展开,往外层展开。

由外层向里层,如果碰到的是以非#开头的宏,继续往里层走,直至最里层,开始一层层往外层展开。

故h(f(1,2))--->h(12)--->g(12)---->#12----->"12"。

PS:

##在宏中定义,是字符连接符

如a##b##c 等同于 "abc"

#在宏开头出现,是表示宏展开的方式不同

#a 等同于"a"

#abc 等同于 "abc"

复杂的:

#include

#define f(a,b) a##b

#define g(a) #a

#define h(a) g(a)

int main()

{

char a = 'a';

cout<

cout<

printf("%s\n", h(f(1,2))); // 12

printf("%s\n", g(f(1,2))); // f(1,2)

printf("%s\n", g(h(f(1,2)))); // h(f(1,2))

printf("%s\n", h(g(f(1,2)))); // "f(1,2)"

printf("%s\n", h(h(f(1,2)))); // "12"

system("pause");

return 0;

}

预处理后的:(在编译选项中添加/EP /P后编译生成的.i文件)

int main()

{

char a = 'a';

cout<

cout<

printf("%s\n", "12");

printf("%s\n", "f(1,2)");

printf("%s\n", "h(f(1,2))");

printf("%s\n", "\"f(1,2)\"");

printf("%s\n", "\"12\"");

system("pause");

return 0;

}

---------------------------------------------------

宏解析

1. ##操作符

##操作符它的作用是在替代表中将其前后的参数连接成为一个预处理符号,它不能出现于宏替代表的开端和末尾。

例:

#define concat(s,t) s##t

#define AAA ABC

concat(A, AA)

将被替换成

ABC

2. 重新扫描和替换

在替换列表中的所有参数替换过之后,预处理器将对结果token序列重新扫描以便对其中的宏再次替换。

当正在替换的宏在其替换列表中发现自身时,就不再对其进行替换。今儿,在任何正在嵌套替换的宏的替换过程中遇到正被替换的宏就对其不再进行替换(防止递归)。

例:

#define ROOT AAA CCC

#define AAA ROOT

ROOT

将被替换成

ROOT CCC

------解决方案--------------------

Token-Pasting Operator (##)

The double-number-sign or “token-pasting” operator (##), which is sometimes called the “merging” operator, is used in both object-like and function-like macros. It permits separate tokens to be joined into a single token and therefore cannot be the first or last token in the macro definition.

If a formal parameter in a macro definition is preceded or followed by the token-pasting operator, the formal parameter is immediately replaced by the unexpanded actual argument. Macro expansion is not performed on the argument prior to replacement.

Then, each occurrence of the token-pasting operator in token-string is removed, and the tokens preceding and following it are concatenated. The resulting token must be a valid token. If it is, the token is scanned for possible replacement if it represents a macro name. The identifier represents the name by which the concatenated tokens will be known in the program before replacement. Each token represents a token defined elsewhere, either within the program or on the compiler command line. White space preceding or following the operator is optional.

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值