使用预处理器进行字符串连接
是否可以在预处理期间连接字符串?
我找到了这个例子
#define H "Hello " #define W "World!" #define HW HW printf(HW); // Prints "Hello World!"
但它对我不起作用 – 当我使用gcc -std=c99
时打印出“Hello”
UPD这个例子现在看起来像是在工作。 但是,它是c预处理器的常规function吗?
相邻字符串litterals的连接不是预处理器的一个特性,它是核心语言(C和C ++)的一个特性。 你可以写:
printf("Hello " " world\n");
你确实可以在预处理器中连接令牌,但要小心,因为它很棘手。 关键是##运算符。 如果你把它放在代码的顶部:
#define myexample(x,y,z) int example_##x##_##y##_##z## = x##y##z
那么基本上,它的作用是,在预处理期间,它将对该宏进行任何调用,如下所示:
myexample(1,2,3);
它将逐渐变成
int example_1_2_3 = 123;
如果您正确使用它,这可以让您在编码时获得很大的灵活性,但它并不完全适用于您尝试使用它的方式。 通过一些按摩,你可以让它工作。
您的示例的一种可能解决方案可能是:
#define H "Hello " #define W "World!" #define concat_and_print(a, b) cout << a << b << endl
然后做类似的事情
concat_and_print(H,W);
来自gcc在线文档 :
‘##’预处理运算符执行标记粘贴。 扩展宏时,每个’##’运算符两侧的两个标记组合成一个标记,然后在宏扩展中替换’##’和两个原始标记。
考虑一个解释命名命令的C程序。 可能需要一个命令表,可能是一个声明如下的结构数组:
struct command { char *name; void (*function) (void); }; struct command commands[] = { { "quit", quit_command }, { "help", help_command }, ... };
如果必须给每个命令名两次,一次在字符串常量中,一次在函数名中,则更清楚。 将命令名称作为参数的宏可以使其不必要。 可以使用字符串化创建字符串常量,并通过将参数与
_command
连接来创建函数名称。 以下是它的完成方式:#define COMMAND(NAME) { #NAME, NAME ## _command } struct command commands[] = { COMMAND (quit), COMMAND (help), ... };
我只是想我会添加一个答案,引用来源说明为什么这样做。
C99标准§5.1.1.2定义了C代码的转换阶段。 第6小节规定:
- 相邻的字符串文字标记是连接的。
同样,在C ++标准(ISO 14882)中,§2.1定义了翻译阶段。 这里第6小节指出:
6连接相邻的普通字符串文字标记。 相邻的宽字符串文字标记被连接在一起。
这就是为什么你可以简单地将字符串放在彼此旁边来连接字符串:
printf("string"" one\n"); >> ./a.out >> string one
问题的预处理部分只是使用#define
预处理指令,该指令执行从标识符( H
)到字符串( "Hello "
)的替换。