Comment

Comment by ryanprichard

The example does not actually use compound literals. (i.e. _arg's initializer would work in C89.) It does use two other C99 features, though -- variadic macros and a for-loop-scoped variable declaration. The biggest compatibility issue, though, are its use of GCC extensions:

- Statement expressions: e.g.: int x = ({ int y = 0; y; });

- If zero-args are allowed (e.g. bar()), then _args is 0-sized, which is also non-standard.

These GCC extensions are somewhat common. Clang has them, and (I think) EDG's frontend does too. MSVC does not have either of them, even in MSVC 2015.

That said, a compound literal might be a good way to remove the extension use, but as long as bar() returns void, the do-while(0) trick is also sufficient for replacing the statement expression.

I think this compound literal usage works:

  #define bar(...) (bar( \
      sizeof((const char*[]) { NULL, __VA_ARGS__ }) / sizeof(const char*) - 1, \
      (const char*[]) { NULL, __VA_ARGS__ } + 1))
bar() results in trailing commas. My impression is that C99 allows them in array initializers. (I saw an example in the n1256 C draft.) I don't recall whether C89 also had them. __VA_ARGS__ is expanded twice, but I think that's OK, because sizeof() only evaluates its operand when it has VLA type, and it never will. This code will work in MSVC 2013 (if not earlier).
parent ryanprichard 10 years ago

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton