31

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

UPD This example looks like working now. However, is it a normal feature of c preprocessor?

5 Answers 5

50

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");
Sign up to request clarification or add additional context in comments.

Comments

24

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);

3 Comments

Is this a c++ standard or just a gcc feature?
In your example, concatenation is done at runtime not by the preprocessor.
Should you use int example_##x##_##y##_##z = x##y##z ?
14

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),
   ...
 };

Comments

7

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 ").

1 Comment

I notice that Mingw resolves string literals at the preprocessing stage. As concatenation operator doesn't work inside string literals.
0

With clang on macos however it seems to not work anymore. On macos clang the concatenation seems broken (example macro_broken.cpp):

#define CONCAT(p1,p2)  p1##p2

int CONCAT(hello,world) = 2;
 cpp --version                                                                     wschrep@walter
Apple clang version 15.0.0 (clang-1500.1.0.2.5)
Target: x86_64-apple-darwin23.1.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

cpp macro_broken.cpp

this outputs:

 1 "macro_broken.cpp"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 384 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "macro_broken.cpp" 2


int hello##world = 2;

instead of what it should be:

int helloworld = 2;

So a##b does not concatenate here. Similarly the handy #a -> "a" also does not work.

A workaround is to use more params to our x macros in order to have different versions (but definately not ideal)

#define PLUGIN_METHODS \
  METHOD(plugin_execute_t, plugin_execute,  "plugin_execute", void,  void)  \
  METHOD(plugin_add_t,     plugin_add,      "plugin_add",     bool,  int, int) \
  METHOD(plugin_sub_t,     plugin_sub,      "plugin_sub",     int,   int, int)      


// generate typedef statements 
// example: 
//   typedef void (*plugin_execute_t)(void);
#define METHOD(name_t, name, name_str, ret, ...) typedef ret (*name_t)(__VA_ARGS__);
PLUGIN_METHODS
#undef METHOD

// generate function pointers
// example:
//   plugin_add_t plug_add = NULL;
#define METHOD(name_t, name, name_str, ret, ...) name_t name = NULL;
PLUGIN_METHODS
#undef METHOD

1 Comment

A workaround is to pass in more params to our x macro in order to avoid having to use the # and ## operations on macos. However our PLUGIN_METHODS define is more tedious to maintain.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.