https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33877
--- Comment #14 from Alejandro Colomar <foss+...@alejandro-colomar.es> --- I've been experimenting with __VA_OPT__(,) and ,##__VA_ARGS__ and I need to make a self correction: While the behavior of __VA_OPT__(,) is not consistent with that of __VA_ARGS__, it is useful, to detect empty macro arguments, and differentiate them from non-empty ones. Now, for __VA_ARGC__, I'm not sure what we should consider for the number of arguments. Consistency is unclear, because __VA_OPT__ is not consistent with __VA_ARGS__, so whichever behavior we define, it would be inconsistent with either __VA_OPT__ or __VA_ARGS__. So, I think existing practice should be followed. I've been researching macros in the wild to calculate numbers of arguments, and they differ in the value they return. Here's the source code I'm using to test different implementations of COUNT_ARGS() that I've found in the wild: #define FOO(...) __LINE__: foo: ARGC(__VA_ARGS__) #define BAR(a, ...) __LINE__: bar: ARGC(__VA_ARGS__) FOO(,,,a) FOO(,,,) FOO(,,a) FOO(,,) FOO(,a) FOO(,) FOO(a) FOO() BAR(,,,a) BAR(,,,) BAR(,,a) BAR(,,) BAR(,a) BAR(,) BAR(a) BAR() All the implementations I've seen, fall into either of these two behaviors: Behavior A: $ gcc -E argcA.c | grep -v ^# 80: foo: 4 81: foo: 4 82: foo: 3 83: foo: 3 84: foo: 2 85: foo: 2 86: foo: 1 87: foo: 1 89: bar: 3 90: bar: 3 91: bar: 2 92: bar: 2 93: bar: 1 94: bar: 1 95: bar: 1 96: bar: 1 Behavior B: $ gcc -E argc2.c | grep -v ^# 16: foo: 4 17: foo: 4 18: foo: 3 19: foo: 3 20: foo: 2 21: foo: 2 22: foo: 1 23: foo: 0 25: bar: 3 26: bar: 3 27: bar: 2 28: bar: 2 29: bar: 1 30: bar: 0 31: bar: 0 32: bar: 0 So, either they consider there's always at least an argument, or there's never one argument. It's possible to write one that using __VA_OPT__ would differentiate 0 and 1 depending on the argument being empty or not, but probably because these macros are older than C23, they don't do it. $ gcc -E argc3.c | grep -v ^# 22: foo: 6 23: foo: 6 24: foo: 5 25: foo: 4 26: foo: 3 27: foo: 2 28: foo: 2 29: foo: 1 30: foo: 0 32: bar: 5 33: bar: 5 34: bar: 4 35: bar: 3 36: bar: 2 37: bar: 1 38: bar: 0 39: bar: 0 40: bar: 0 The former seems to never have 0 arguments, even for this case: #define BAR(a, ...) __LINE__: bar: ARGC(__VA_ARGS__) BAR(a) 95: bar: 1 This seems very unnatural, both from the point of view of ,##__VA_ARGS__, and from the point of view of __VA_OPT__. The latter seems consistent with __VA_OPT__, which seems okay. None of the macros I found seem consistent with ,##__VA_ARGS__. So, I guess we should have __VA_ARGC__ be consistent with __VA_OPT__.