I have some issue with this code i written. GCC does not like it :
#define _DEBUG_ADD(string, ...) \
do{ \
if (EVALUATE_TYPE(string)){ \
size_t size = strlen(string) + BUFFER_SIZE_DEBUG; \
char *buffer = alloca(size); \
bzero(buffer, size); \
snprintf(buffer, size, string, __VA_ARGS__); \
fwrite(buffer, strlen(buffer), 1, DEBUG_STREAM); }} \
while(0)
But gcc display this error :
../debug.h:33:42: error: expected expression before ')' token
snprintf(buffer, size, string, __VA_ARGS__);
I read the gcc doc about variadic macro and i am not doing it wrong.
Can someone point my mistake ? I am completly lost.
edit :
I use it that way
_DEBUG_ADD("Bbox found @ %f %f %f %f", box[0], box[1], box[2], box[3]);
If I take the code fragments you showed and fill in missing bits to get a complete, compilable source file, I do not get any errors:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define _DEBUG_ADD(string, ...) \
do{ \
if (EVALUATE_TYPE(string)){ \
size_t size = strlen(string) + BUFFER_SIZE_DEBUG; \
char *buffer = alloca(size); \
bzero(buffer, size); \
snprintf(buffer, size, string, __VA_ARGS__); \
fwrite(buffer, strlen(buffer), 1, DEBUG_STREAM); }} \
while(0)
#define EVALUATE_TYPE(s) 1
#define BUFFER_SIZE_DEBUG 128
#define DEBUG_STREAM stderr
void test(double box[4])
{
_DEBUG_ADD("Bbox found @ %f %f %f %f", box[0], box[1], box[2], box[3]);
}
-->
$ gcc -fsyntax-only -Wall test.c
$
This is why we make such a fuss about minimal, complete, verifiable examples. We don't want to waste a lot of time barking up the wrong tree.
However, in this case, I have a strong suspicion that your problem was actually triggered by code like this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define _DEBUG_ADD(string, ...) \
do{ \
if (EVALUATE_TYPE(string)){ \
size_t size = strlen(string) + BUFFER_SIZE_DEBUG; \
char *buffer = alloca(size); \
bzero(buffer, size); \
snprintf(buffer, size, string, __VA_ARGS__); \
fwrite(buffer, strlen(buffer), 1, DEBUG_STREAM); }} \
while(0)
#define EVALUATE_TYPE(s) 1
#define BUFFER_SIZE_DEBUG 128
#define DEBUG_STREAM stderr
void test(void)
{
_DEBUG_ADD("got here 1");
}
which produces nearly the same error message you showed:
$ gcc -fsyntax-only -Wall test.c
test.c: In function ‘test’:
test.c:11:43: error: expected expression before ‘)’ token
snprintf(buffer, size, string, __VA_ARGS__); \
^
test.c:21:3: note: in expansion of macro ‘_DEBUG_ADD’
_DEBUG_ADD("got here 1");
^~~~~~~~~~
When you give _DEBUG_ADD
no arguments after the format string, __VA_ARGS__
expands to nothing, so the "compiler proper" sees
snprintf(buffer, size, string, );
which is indeed a syntax error. This is what the GNU comma-deletion extension is for: if you put ##
between ,
and __VA_ARGS__
, the comma will be removed when __VA_ARGS__
expands to nothing.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define _DEBUG_ADD(string, ...) \
do{ \
if (EVALUATE_TYPE(string)){ \
size_t size = strlen(string) + BUFFER_SIZE_DEBUG; \
char *buffer = alloca(size); \
bzero(buffer, size); \
snprintf(buffer, size, string, ##__VA_ARGS__); \
fwrite(buffer, strlen(buffer), 1, DEBUG_STREAM); }} \
while(0)
#define EVALUATE_TYPE(s) 1
#define BUFFER_SIZE_DEBUG 128
#define DEBUG_STREAM stderr
void test(void)
{
_DEBUG_ADD("got here 1");
}
-->
$ gcc -fsyntax-only -Wall test.c
$
Unfortunately, this extension is only available in GCC and Clang. I understand the C and C++ committees are talking about adding a comparable, but incompatible, feature Real Soon Now (see the comments on this question and its answers, and also C committee documents N2023 and N2153), but even if they do, it'll probably be a decade or so before that's ubiquitous enough to use.
Incidentally, the name _DEBUG_ADD
begins with an underscore. All names beginning with underscores are reserved for internal use by the C compiler and library in at least some contexts. Until you have a lot more experience in the language, you should not give anything in your code a name beginning with an underscore. (It is OK to use things with names that begin with underscores, like __VA_ARGS__
and _IONBF
, but only if they are documented.)