String concatenation using preprocessor

前端 未结 4 1823
南方客
南方客 2020-12-11 00:33

is it possible to concatenate strings during preprocessing?

I found this example

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

printf(HW)         


        
相关标签:
4条回答
  • 2020-12-11 00:44

    Concatenation of adjacent string litterals isn't a feature of the preprocessor, it is a feature of the core languages (both C and C++). You could write:

    printf("Hello "
           " world\n");
    
    0 讨论(0)
  • 2020-12-11 00:48

    From gcc online docs:

    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. 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. Here is how it is done:

     #define COMMAND(NAME)  { #NAME, NAME ## _command }
    
     struct command commands[] =
     {
       COMMAND (quit),
       COMMAND (help),
       ...
     };
    
    0 讨论(0)
  • 2020-12-11 00:58

    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);
    
    0 讨论(0)
  • 2020-12-11 01:00

    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. Subsection 6 states:

    1. Adjacent string literal tokens are concatenated.

    Similarly, in the C++ standards (ISO 14882) §2.1 defines the Phases of translation. Here Subsection 6 states:

    6 Adjacent ordinary string literal tokens are concatenated. 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 ").

    0 讨论(0)
提交回复
热议问题