Question

In C, I'd like to make a function or a macro that looks like this:

void Log(char* what, ...) 

where the ... must be key-value pairs of const char*'s. I would really like code that doesn't follow this to blow up at compile time. I tried looking for an __attribute((..)) directive that did this, to no avail. Any ideas?

Was it helpful?

Solution 2

where the ... must be key-value pairs of const char*'s

Then you don't want variadic arguments at all. If you know the type(s) you are expecting beforehand then you don't need it and you're just making things more difficult than they need to be.

Just pass in an array.

void Log(const char *what, const char **args, size_t size);

OTHER TIPS

C has no way to enforce type safety over arbitrary variadic arguments. GCC and Clang have __attribute__s for some fixed cases (when a variadic function expects the last argument to be NULL, you can use __sentinel__; or when it's a format string, you can use format), but there is no generic solution.

On the other hand, C++11 has variadic templates to solve this problem, but since you mentioned that you're working in C, it's not gonna work for you.

Okay, I figured out a workaround:

#define ASSERT_LIST_TYPE(t, l...) do{t _t[] = {l};}while(0)

void _Log(char* what, ...);

#define Log(what, args...) do{\
  ASSERT_LIST_TYPE(char*, args);\
 _Log(what, args);\
}while(0)

That at least generates a warning if the args aren't of the right type, because the dummy array initialization isn't of the right type.

I plan on #ifdef'ing the ASSERT_LIST_TYPE out if this isn't a debug build just in case..

** Edit **

Based on the feedback in here, I changed the code to look like this:

void _Log(char* what, const char** args, size_t args_len);

#define Log(what, args...) do{\
  const char* a[] = {args};\
  _Log(what, a, (sizeof a)/sizeof(char*));
}while(0)

This appears to work even if args is empty, and it catches somebody passing an obj-c literal string instead (@"..." instead of "...") which is what bit me before.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top