使用预处理器进行字符串连接

Vla*_*hev 19 c c++ string

是否可以在预处理期间连接字符串?

我找到了这个例子

#define H "Hello "
#define W "World!"
#define HW H W

printf(HW); // Prints "Hello World!"
Run Code Online (Sandbox Code Playgroud)

然而它对我不起作用 - 当我使用时打印出"Hello" gcc -std=c99

UPD这个例子现在看起来像是在工作.但是,它是c预处理器的正常功能吗?

APr*_*mer 41

相邻字符串litterals的连接不是预处理器的一个特性,它是核心语言(C和C++)的一个特性.你可以写:

printf("Hello "
       " world\n");
Run Code Online (Sandbox Code Playgroud)


NDL*_*NDL 20

你确实可以在预处理器中连接令牌,但要小心,因为它很棘手.关键是##运算符.如果你把它放在代码的顶部:

#define myexample(x,y,z) int example_##x##_##y##_##z## = x##y##z 
Run Code Online (Sandbox Code Playgroud)

那么基本上,它的作用是,在预处理期间,它将对该宏进行任何调用,如下所示:

myexample(1,2,3);
Run Code Online (Sandbox Code Playgroud)

它将真正变成

int example_1_2_3 = 123;
Run Code Online (Sandbox Code Playgroud)

如果您正确使用它,这将使您在编码时具有很大的灵活性,但它并不完全适用于您尝试使用它的方式.通过一些按摩,你可以让它工作.

您的示例的一种可能解决方案可能是:

#define H "Hello "
#define W "World!"
#define concat_and_print(a, b) cout << a << b << endl
Run Code Online (Sandbox Code Playgroud)

然后做类似的事情

concat_and_print(H,W);
Run Code Online (Sandbox Code Playgroud)

  • 在您的示例中,连接是在运行时完成的,而不是由预处理器完成的。 (2认同)

小智 12

来自gcc在线文档:

'##'预处理运算符执行标记粘贴.扩展宏时,每个'##'运算符两侧的两个标记组合成一个标记,然后在宏扩展中替换'##'和两个原始标记.

考虑一个解释命名命令的C程序.可能需要一个命令表,可能是一个声明如下的结构数组:

 struct command
 {
   char *name;
   void (*function) (void);
 };

 struct command commands[] =
 {
   { "quit", quit_command },
   { "help", help_command },
   ...
 };
Run Code Online (Sandbox Code Playgroud)

如果必须给每个命令名两次,一次在字符串常量中,一次在函数名中,则更清楚.将命令名称作为参数的宏可以使其不必要.字符串常量可以使用字符串化创建,函数名称可以通过连接参数来创建_command.以下是它的完成方式:

 #define COMMAND(NAME)  { #NAME, NAME ## _command }

 struct command commands[] =
 {
   COMMAND (quit),
   COMMAND (help),
   ...
 };
Run Code Online (Sandbox Code Playgroud)


Mik*_*ike 6

我只是想我会添加一个答案,引用来源说明为什么这样做.

C99标准§5.1.1.2定义了C代码的转换阶段.第6小节规定:

  1. 相邻的字符串文字标记是连接的.

类似地,在C++标准(ISO 14882)中,§2.1定义了翻译阶段.这里第6小节指出:

6连接相邻的普通字符串文字标记.相邻的宽字符串文字标记是连接的.

这就是为什么你可以简单地通过将字符串放在彼此旁边来连接字符串:

printf("string"" one\n");

>> ./a.out
>> string one
Run Code Online (Sandbox Code Playgroud)

问题的预处理部分只是使用#define预处理指令,它执行从identifier(H)到string("Hello ")的替换.