#include <stdio.h>
// #(stringizing) 字符串化操作符。
// 作用:将宏定义中的传入参数名转换成用一对双引号括起来的参数名字符串。
// 其只能用于有参数传入的宏定义中,且必须置于宏定义参数名前面。
// 对空格的处理:
// 1. 忽略传入参数名前后的空格;
// 2. 当传入参数名的中间存在空格时,编译器会自动连接各子字符串,
// 且每个子字符串中只以一个空格连接,忽略多余一个的空格。
#define EXP(x) printf("The string is: \"%s\"\n", #x)
#define PRINT(x) printf("\"%s\": ", #x);\
printf("%d", x) // 因为语句本身不能判断参数类型,所以显得不那么方便
// 使用下面 C++ 的 cout 语法,可以很方便的输出;
// 在C++中的妙用
// #define P(A) cout<<#A<<": "<<(A)<<endl;
#define TEST 123
int main(void)
{
int abc = 5;
EXP(5); // output: "5"
EXP(abc); // output: "abc"
EXP( abc def hig ); // output: "abc def hig"
EXP(TEST); // output: "TEST" // 即使参数也算一个宏定义,但是不会再展开了;即不能嵌套
EXP(EXP(TEST)); // output: "EXP(TEST)"
PRINT(abc); // output: ["abc": 5]
return 0;
}
#include <stdio.h>
// ##: 记号粘贴操作符(token paste operator)
// 作用:先分隔,然后进行强制连接。
// 普通宏定义中,预处理器一般把空格解释成分段标志,对每一段和前面比较,
// 相同的就被替换,但是这样的结果是:被替换后空格还是存在。
// 如果我们不希望出现这些空格,就可以通过 "##" 代替空格。
// 如果 ## 前面出现空格,也会被编译器忽略。
// 解释:这里的分隔类似于:"#define add(a,b) a+b" 中的 "+" 的作用,将两个参数分开。
// 以下实例可用于命名标准化
#define A1(name, type) type name_##type##_type // 分隔成:"name_", "type", "_type" 三个token,所以只有 "type" 能匹配上
#define A2(name, type) type name##_##type##_type // 分隔成:"name", "_","type", "_type" 四个token,所以 "name", "type" 都能匹配上
#define A3(name, type) type name ##_##type ##_type // ## 前出现空格,被编译器忽略;
int main(void)
{
A1(a1, int); // 相当于: int name_int_type;
A2(a2, float); // 相当于: float a2_float_type;
A3(a3, double);
name_int_type = 5; // 编译正确,说明变量 name_int_type 已经存在;
a2_float_type = 3.14; // 编译正确,说明变量 a2_float_type 已经存在;
a3_double_type = 3.1415926; // 编译正确,说明变量 a3_double_type 已经存在;
return 0;
}
#include <stdio.h>
#define VAR1 123
#define stringizing(param) #param
#define TO_STR(a) stringizing(a)
#define F abc
#define B def
#define FB(arg) #arg
#define FB1(arg) FB(arg)
#define CONN(a, b) a##b
#define pasiting(n) printf("token" #n " = %d\n", token##n)
int main()
{
printf("%s\n", TO_STR(VAR1)); // output: "123"
printf("%s\n", stringizing(VAR1)); // output: "VAR1"
printf("%s\n", FB(F B)); // output: "F B"
printf("%s\n", FB1(F B)); // output: "abc def"
int token9 = 8;
int CONN(token, 8) = 7;
printf("%s = %d\n", TO_STR(CONN(token, 8)), CONN(token, 8)); // output: "token8 = 7"
printf("%s\n", TO_STR(CONN(x, y))); // output: "xy"
// printf("%s\n", TO_STR(CONN(CONN(a, b), c))); // 编译出错,CONN不可嵌套使用
pasiting(9); // output: "token9 = 8"
return 0;
}
参考: