https://blog.csdn.net/mary288267/article/details/116499135
1.C语言中嵌套宏的展开规律
一般宏调用的展开规律是,先展开内层宏参数,再展开外层宏函数,所以展开顺序是由内而外。
如果宏定义中某个形参前面有#运算符,则调用此宏定义时,不展开该形参对应的实参,而是直接把这个实参变为字符串。
如果宏定义中某个形参前面有#@运算符,则调用此宏定义时,不展开该形参对应的实参,而是直接把这个实参变为字符。
如果宏定义中某个形参前面或者后面有##运算符,则调用此宏定义时,不展开该形参对应的实参,而是将##运算符前后的实参连接到一起形成一个新的符号,注意不是字符串。
详细实例可见下述代码。
备注:本文参考了 以下链接并作修改。链接:https://blog.csdn.net/aflyeaglenku/article/details/81504256
#include<stdio.h>
#include<iostream>
using namespace std;
#define A(x) T_##x
#define B(x) #@x
#define C(x) #x
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
#define ff(x,y) x+y
#define foo abc
#define foo2(x) x##123
#define foo123 "hehe"
#define Str1 "hello"
#define Cat2Str(x,y) x#y
void main()
{
printf("%c\n", B(1)); // B(1)------〉'1'
printf("%s\n", C(1)); // C(1)------〉"1"
printf("%s\n", h(A(1)));
//输出:T_1。
//宏展开过程为:因h(a)的宏形参前没有#或#@,形参前后没有##,因此先展开宏参数A(1)。
//h(A(1))→h(T_1)→g(T_1)→"T_1"
printf("%s\n", h(f(1, 2)));
//输出:12.
//宏展开过程为:因宏h(a)的宏形参前没有#或#@,形参前后没有##,因此先展开宏参数。
//h(f(1, 2))→h(12)→g(12)→"12"
printf("%s\n", g(f(1, 2)));
//输出:f(1,2)
//宏展开过程为:因宏g(a)宏定义的形参前有#,则不展开实参f(1,2),而是把实参作为字符串。
//g(f(1, 2))→#f(1,2)→"f(1,2)"
printf("%d\n", f(f, f(3, 4)));
//输出:7。
//宏展开顺序为:因宏定义f(a,b)的形参前后有##,因此,不展开实参, f(f, f(3, 4))→ff(3,4)→3+4
printf("%s\n", g(1)g(2)); //输出:12
//这个例子很特殊,我原以为编译器不会识别g(1)g(2),事实上,编译后会识别连在一起的宏,然后分别展开。
printf("%s\n", f(g(1), g(2))); //输出:12
//宏展开过程为:因宏定义f(a,b)的形参前后有##,所以不展开实参g(1)和g(2),f(g(1), g(2))展开后变为g(1)g(2),
//f(g(1), g(2))→g(1)##g(2)→g(1)g(2)→“12”
printf("%s\n", Cat2Str(Str1, ",nihao")); //输出:hello",nihao"
printf("%s\n", Cat2Str(Str1, Str1)); //输出:helloStr1
//这个例子也比较经典,当宏定义某个形参前有#时,对应宏调用的实参被当作字符串
//Cat2Str(Str1, Str1)宏展开过程为:
//因为Cat2Str(x,y)的y参数前有#,直接将后面的参数转为字符串
//Cat2Str(Str1, Str1)→"hello""Str1"→"helloStr1"
printf("%s\n", foo2(foo));
//最后,上个经典例子吧。 foo2(foo)的展开可不是abc123哦。
//宏展开过程为:因为foo2(x)的宏定义形参前有##,因此,foo2(foo)对应的实参foo不再展开。
//foo2(foo)→foo##123→foo123→"hehe"
}
宏对应的数值需要使用字符串和数字时
代码1:
void testHong()
{
#define RATE_RAW (15000) // 需要字符串时使用这个
#define RATE (RATE_RAW) // 需要数字时使用这个
#define STR1(R) #R
#define STR2(R) STR1(R)
printf("sample rate is %d\n", RATE);
printf("sample rate = " STR2(RATE_RAW) "\n");
}
sample rate is 15000
sample rate = (15000)
代码2:
void testHong()
{
#define RATE_RAW 15000 // 需要字符串时使用这个
#define RATE (RATE_RAW) // 需要数字时使用这个
#define STR1(R) #R
#define STR2(R) STR1(R)
printf("sample rate is %d\n", RATE);
printf("sample rate = " STR2(RATE_RAW) "\n");
}
sample rate is 15000
sample rate = 15000