Title: va-args not resolving correctly
Tags: c;variadic-functions
Question: I have the following function:

```void Register(Data* _pData, uint32 _Line, const char* _pFile, ...)
{
   va_list Args;
   va_start(Args, _pFile);
   for(uint i = 0;i m_NumFloats; ++i)
   {
      _pData->m_Floats[i] = va_arg(Args, fp32);
   }
   va_end(Args);
}
```

Which is called by the macro:

```#define REG(_Name, ...)\
{\
   if(s_##_Name##_Data.m_Enabled)
      Register(&s_##_Name##_Data, __LINE__, __FILE__, ##__VA_ARGS__);\
}\
```

With the usage:

```REG(Test, (fp32)0.42f);
```

The Data-struct looks like:

```
struct Data
{
   int m_NumFloats;
   fp32 m_Floats[4];
}
```

The creation-macro of Data creates the static ```Data g_YourName_Data``` and initializes it correctly with a maximum of 4 m_NumFloats. 

The va_arg call resolves to 0.0. s_Test_Data exists and the Register-function is called appropriate. va-list just simply won't let me resolve the first argument into the float that I passed it into. Is there anything specific that I'm missing?

Comment: @AndreyT "What is ## doing in front of `__VA_ARGS__`?" - it is making it possible for a variadic macro to receive zero arguments.

Comment: @AndreyT This is a special construct, I'm not sure whether or not it is standard. The preprocessor will elimate the trailing comma if `__VA_ARG__` is preceded by the token pasting operator and there are no variadic arguments.

Comment: There is no `_Name_Data`. It's a macro using `_Name` to find a statically declared object which in this case expands to `_Test_Data`. So the macro does use `_Name`. The `##` Is used to strip the `,` if no actual extra parameters are passed.

Comment: What is `_Name_Data`? Why are you declaring `_Name` parameter in your macro, when your macro definition does not use `_Name` anywhere at all? What is `##` doing in front of `__VA_ARGS__`?

Comment: @H2CO3: Could you elaborate a bit on that? What difference does it make (compared to the same thing without the `##`)? And how will it help with the issue of trailing `,`?

Here is the accepted answer: Try:

```#define REG(_Name, ...)\
{\
   if(s_##_Name_Data.m_Enabled)\
      Register(&amp;s_##_Name_Data, __LINE__, __FILE__, __VA_ARGS__);\
}
```

Get rid of the token-pasting operator.  You we're also missing a '\' in your macro (maybe a copy-n-paste error?).

Also, use ```va_arg()```, not ```va_args()```.  And I'm not sure if you meant for ```_Name``` to be ```_Name_Data``` or the other way around.

Finally, I assumed that ```fp32``` was an alias for ```float```; GCC had this to say to me:

```C:\TEMP\test.c:22: warning: `fp32' is promoted to `double' when passed through `...'
C:\TEMP\test.c:22: warning: (so you should pass `double' not `fp32' to `va_arg')
C:\TEMP\test.c:22: note: if this code is reached, the program will abort
```

You should heed that warning. The program does crash for me if I do not.

Comment for this answer: @Zack - thanks for that information.  I knew the GCC had a way to deal with empty `__VAR_ARGS__`, but didn't remember that that was it.
Comment for this answer: @Simon: "I'm using Microsoft's compiler and not GCC" - I was really, really surprised that GCC diagnosed that problem in a warning.  I doubt that it's something I would have figured out on my (at least not without quite a debugging effort). This is one reason I try to compile snippets with problems using several compilers. Kudos to GCC for diagnosing that.
Comment for this answer: Thanks for the answer Michael, and sorry for the copy-and-paste errors. I'll edit the post to make it correct. I'm not getting any such warnings. The real code handles the case where no va-args are present, the number of arguments expected are defined earlier.Should you really append an extra `\ ` on the last line of the macro? I'm quite certain that you don't need that (since I have several macros which don't have it and it would have caused some compiler errors if it didn't). `_Name` is inserted into the identifier that we're accessing. In this case the identifier would become `s_Test_Data`.
Comment for this answer: Oh, I'm using microsoft's compiler and not GCC.
Comment for this answer: Changing it into reading a `double` made it work though! Thanks a ton!
Comment for this answer: @Michael: Indeed, GCC tend to warn about a lot more than MSVC so I should probably try to set up my build-system to work with GCC as well just to catch more errors. Thanks again!
Comment for this answer: The `, ## __VA_ARGS__` thing is a GCC extension which makes the comma go away if `__VA_ARGS__` expands to no tokens (i.e. if REG() is called with only one argument).  In *this case* it's inappropriate because Register() must receive at least one anonymous argument, and you'd like that to be a compile error rather than garbage at runtime, but it's not automatically wrong.
Comment for this answer: You definitely don't want a backslash on the last line of the macro, it'll suck whatever's on the *next* line of source into the macro as well.  Probably right now that's a blank line and so it's harmless, but then someone comes along and decides that the code would look better without the blank line and hilarity ensues.


{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 1, 'CommentCount': 5, 'ContentLicense': 'CC BY-SA 2.5', 'CreationDate': '2010:00:08/06/10', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<c><variadic-functions>', 'Title': 'va-args not resolving correctly', 'ViewCount': 1367, 'id': 3428575, 'user_AboutMe': '<p>Software Engineer / Professional Game Developer.</p>\n', 'user_AccountId': 171271.0, 'user_DisplayName': 'Simon', 'user_Reputation': 763.0, 'user_Views': 157.0, 'user_id': 398577.0}}