简体   繁体   English

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

[英]String concatenation using preprocessor

is it possible to concatenate strings during preprocessing? 是否可以在预处理期间连接字符串?

I found this example 我找到了这个例子

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

printf(HW); // Prints "Hello World!"

However it does not work for me - prints out "Hello" when I use gcc -std=c99 但它对我不起作用 - 当我使用gcc -std=c99打印出“Hello”

UPD This example looks like working now. UPD这个例子现在看起来像是在工作。 However, is it a normal feature of c preprocessor? 但是,它是c预处理器的正常功能吗?

Concatenation of adjacent string litterals isn't a feature of the preprocessor, it is a feature of the core languages (both C and C++). 相邻字符串litterals的连接不是预处理器的一个特性,它是核心语言(C和C ++)的一个特性。 You could write: 你可以写:

printf("Hello "
       " world\n");

You can indeed concatenate tokens in the preprocessor, but be careful because it's tricky. 你确实可以在预处理器中连接令牌,但要小心,因为它很棘手。 The key is the ## operator. 关键是##运算符。 If you were to throw this at the top of your code: 如果你把它放在代码的顶部:

#define myexample(x,y,z) int example_##x##_##y##_##z## = x##y##z 

then basically, what this does, is that during preprocessing, it will take any call to that macro, such as the following: 那么基本上,它的作用是,在预处理期间,它将对该宏进行任何调用,如下所示:

myexample(1,2,3);

and it will literally turn into 它将真正变成

int example_1_2_3 = 123;

This allows you a ton of flexibility while coding if you use it correctly, but it doesn't exactly apply how you are trying to use it. 如果您正确使用它,这将使您在编码时具有很大的灵活性,但它并不完全适用于您尝试使用它的方式。 With a little massaging, you could get it to work though. 通过一点点按摩,你可以让它工作。

One possible solution for your example might be: 您的示例的一种可能解决方案可能是:

#define H "Hello "
#define W "World!"
#define concat_and_print(a, b) cout << a << b << endl

and then do something like 然后做类似的事情

concat_and_print(H,W);

From gcc online docs : 来自gcc在线文档

The '##' preprocessing operator performs token pasting. '##'预处理运算符执行标记粘贴。 When a macro is expanded, the two tokens on either side of each '##' operator are combined into a single token, which then replaces the '##' and the two original tokens in the macro expansion. 扩展宏时,每个'##'运算符两侧的两个标记组合成一个标记,然后在宏扩展中替换'##'和两个原始标记。

Consider a C program that interprets named commands. 考虑一个解释命名命令的C程序。 There probably needs to be a table of commands, perhaps an array of structures declared as follows: 可能需要一个命令表,可能是一个声明如下的结构数组:

  struct command { char *name; void (*function) (void); }; struct command commands[] = { { "quit", quit_command }, { "help", help_command }, ... }; 

It would be cleaner not to have to give each command name twice, once in the string constant and once in the function name. 如果必须给每个命令名两次,一次在字符串常量中,一次在函数名中,则更清楚。 A macro which takes the name of a command as an argument can make this unnecessary. 将命令名称作为参数的宏可以使其不必要。 The string constant can be created with stringification, and the function name by concatenating the argument with _command . 可以使用字符串化创建字符串常量,并通过将参数与_command连接来创建函数名称。 Here is how it is done: 以下是它的完成方式:

  #define COMMAND(NAME) { #NAME, NAME ## _command } struct command commands[] = { COMMAND (quit), COMMAND (help), ... }; 

I just thought I would add an answer that cites the source as to why this works. 我只是想我会添加一个答案,引用来源说明为什么这样做。

The C99 standard §5.1.1.2 defines translation phases for C code. C99标准§5.1.1.2定义了C代码的转换阶段。 Subsection 6 states: 第6小节规定:

  1. Adjacent string literal tokens are concatenated. 相邻的字符串文字标记是连接的。

Similarly, in the C++ standards (ISO 14882) §2.1 defines the Phases of translation. 类似地,在C ++标准(ISO 14882)中,§2.1定义了翻译阶段。 Here Subsection 6 states: 这里第6小节指出:

6 Adjacent ordinary string literal tokens are concatenated. 6连接相邻的普通字符串文字标记。 Adjacent wide string literal tokens are concatenated. 相邻的宽字符串文字标记是连接的。

This is why you can concatenate strings simply by placing them adjacent to one another: 这就是为什么你可以简单地将字符串放在彼此旁边来连接字符串:

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

>> ./a.out
>> string one

The preprocessing part of the question is simply the usage of the #define preprocessing directive which does the substitution from identifier ( H ) to string ( "Hello " ). 问题的预处理部分只是使用#define预处理指令,该指令执行从标识符( H )到字符串( "Hello " )的替换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM