6

Example code:

#define FOO(...) You passed: #__VA_ARGS__
FOO(1,2,3)
FOO()

Preprocess with Visual C++ (version 14 CTP), get:

You passed: "1,2,3"
You passed:

In the last line, #__VA_ARGS__ is turned into nothingness. I would prefer it turned into "".

Is there a definitive reference for what is supposed to happen? I Googled a lot but couldn't find it.

Any suggested work-around would also be useful.

Bryan
  • 11,398
  • 3
  • 53
  • 78
  • It may be unspecified by the standard. I am currently getting `""` when I run under `gcc`'s preprocessor. – merlin2011 Jul 01 '14 at 09:07
  • Did you have a look at the preprocessed source code or is there a chance that you are misinterpreting the output of your test program? – PlasmaHH Jul 01 '14 at 09:08
  • 2
    It doesn't make a difference, does it? You can always concatenate the result into any string you like: `"Hello: " FOO() "!\n"` – Kerrek SB Jul 01 '14 at 09:08

2 Answers2

7

Per 6.10.3.2 The # operator (C11):

Semantics

2 - [...] The character string literal corresponding to an empty argument is "". [...]

So I think MSVC is incorrect here.

I would workaround this using string literal concatenation:

#define FOO(...) You passed: "" #__VA_ARGS__
Community
  • 1
  • 1
ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • Well, VC++ never pretended to implement C99 or C11 fully, so it's hard to say it is incorrect; it just is different. – Matthieu M. Jul 01 '14 at 09:28
4

The paragraph in the standard (ISO14882:2011(e)) is a little bit lengthy, but its quite clear:

16.3.2 The # operator

2 A character string literal is a string-literal with no prefix. If, in the replacement list, a parameter is immediately preceded by a # preprocessing token, both are replaced by a single character string literal preprocessing token that contains the spelling of the preprocessing token sequence for the corresponding argument. Each occurrence of white space between the 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 argument is deleted. Otherwise, the original spelling of each preprocessing token in the argument is retained in the character string literal, except for special handling for producing the spelling of string literals and character literals: a \ character is inserted before each " and \ character of a character literal or string literal (including the delimiting " characters). If the replacement that results is not a valid character string literal, the behavior is undefined. The character string literal corresponding to an empty argument is "". The order of evaluation of # and ## operators is unspecified.

And since

16.3.1 Argument substitution

2 An identifier __VA_ARGS__ that occurs in the replacement list shall be treated as if it were a parameter, and the variable arguments shall form the preprocessing tokens used to replace it.

this is the same for varags as it is for normal parameters.

PlasmaHH
  • 15,673
  • 5
  • 44
  • 57
  • 1
    Thanks; I tried it with a simple argument (`#define FOO(x)`) and it behaves the same. – Bryan Jul 01 '14 at 09:51
  • 1
    @Bryan: Seems like a bug then to me. But ms people like to call such things "features", so unless you ask them (by filing a bugreport) we will never know. – PlasmaHH Jul 01 '14 at 09:59