Aykhan Hagverdili
Aykhan Hagverdili

Reputation: 29985

Why does macro expansion add a space sometimes?

If I do this:

#define F a
F/

It expands to a/ godbolt

If I do this:

#define F /
F/

It expands to / / with a space in between goodbolt

But if I convert it to a string, and print it, it doesn't add any spaces goodbolt:

#include <stdio.h>

#define STR_IMPL(x) #x
#define STR(x) STR_IMPL(x)

#define F /


int main() {
  puts(STR(F/));
}

Why is there a space in between, but only some of the time? Is it allowed to add more spaces in other cases?

Upvotes: 4

Views: 1058

Answers (2)

M.M
M.M

Reputation: 141628

The language specification is like this, at a high level:

  • Break up the input into a sequence of tokens.
  • Run the preprocessor on that sequence of tokens (resulting in another sequence of tokens)
  • Compile that resulting sequence of tokens.

There is no specification of any intermediate plain-text representation between the steps . What you are seeing in the "preprocessor output" is entirely at the whim of the vendor, so long as the final result of the whole translation process behaves as specified.


Analysis of the example with #define F / and STR(F/) :

First note that #define F / followed by newline means that F is replaced by the two tokens w / (where I am using w to mean a whitespace token).

The sequence of preprocessing tokens for STR(F/) after tokenization is:

  • STR, (, F, /, )

After the first round of macro substitution the tokens are:

  • w, STR_IMPL, (, w, /, /, )

After the second round, the tokens are:

  • w, "//" .

The definition of the # preprocessing operator includes that leading whitespace is removed. So the token sequence w, /, / becomes "//", not " //".

There was never any space between the F/ or the two slashes at any point.

Upvotes: 3

Sebastian Redl
Sebastian Redl

Reputation: 72044

Macros work on the token level. Spaces are added when printing the result in string form to disambiguate.

F/ is two tokens, F and /. After macro expansion, it still needs to be two tokens, / and /. But if you print them next to each other, it becomes //, which is just one token (a comment). So there needs to be a space in-between.

Long story short: yes, macro expansion can add spaces, because spaces don't matter at the level macros operate at.

Upvotes: 5

Related Questions