How does the stringify operator expand TABS?

Viewed 72

GCC seems like to always expand tabs in source code by spaces. It preserve space that are inside the expression. What does the standard says about it?

For example, what will c contains in this example (<TAB> represent a litteral \t character in source code file).

#define X(a) #a

const char* c = X(<TAB>a<TAB>c<TAB>);
// c == "a c" ? (looks like what gcc does)
// c == "a\tc" ?
2 Answers

Consulting the C++ standard (draft)'s section [cpp.stringize] tells us:

Each occurrence of whitespace between the stringizing argument's preprocessing tokens becomes a single space character in the character string literal. White space before the first preprocessing token and after the last preprocessing token comprising the stringizing argument is deleted.

Given: <TAB>a<TAB>c<TAB>, the first rule means that we'd have " a c ", but the second rule means that we'd delete the leading and trailing whitespace, giving us "a c" as you saw.

The current ISO CPP (C pre-processor) collapses whitespaces as specified in the other answer. As documented in the GCC docs, using -traditonal-cpp for the preprocessor should preserve whitespaces

The form of horizontal whitespace in the input file is preserved in the output. In particular, hard tabs remain hard tabs. This can be useful if, for example, you are preprocessing a Makefile.

but that too doesn't appear to. So,

$ cat test.cpp|grep 'const'|sed 's/\t/@/g'
   const char* c = X(@a@c@);

but on being pre-processed, the tabs are replaced

$ cpp test.cpp|grep 'const'|sed 's/\t/@/g'
   const char* c = "a c";

and this doesn't differ whatsoever even on using traditional-cpp option

$ cpp -traditional-cpp test.cpp|grep 'const'|sed 's/\t/@/g'
   const char* c = "a c";

This is the output using the GNU compiler set. This is not the case with clang though which works as expected with the -traditional-cpp option

$clang -E -traditional-cpp test.cpp|grep 'const'|sed 's/\t/@/g'
   const char* c = #@a@c@;

This appears to be a bug in GCC. I'm using GCC 9.3 on WSL.

Related