0
#include <stdarg.h>

#define VARGS_CNT(...) VARGS_CNT_LOCAL(, ##__VA_ARGS__,\
 64, 63, 62, 61, 60, \
 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \
 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \
 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \
 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
  9,  8,  7,  6,  5,  4,  3,  2,  1,  0)
#define VARGS_CNT_LOCAL(\
  _0,  _1,  _2,  _3,  _4,  _5,  _6,  _7,  _8,  _9, \
 _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \
 _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \
 _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \
 _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, \
 _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, \
 _60, _61, _62, _63, _64, N, ...) N

#define SUM1(...) ,##__VA_ARGS__
#define SUM(...) sum(VARGS_CNT(__VA_ARGS__) ,##__VA_ARGS__)

int sum(int n, ...) {
    va_list ap;
    va_start(ap, n);
    int res = 0;
    for (int i = 0; i < n; i++) {
        res += va_arg(ap, int);
    }
    return res;
}

int main() {
    int res = SUM();
    int res1 = SUM(1);
    int res2 = SUM(1, 2);
    int res3 = SUM(1, 2, 3);
    return 0;
}

In both GCC and MSVC, the above code compiles and returns correct results.

In Visual Studio, however, an error occurs during source code analysis, as if ##VA_ARGS is empty when expanded without eating the preceding comma ','.

Like the picture below.

enter image description here

But in fact the code expands correctly and is debugged as expected. enter image description here

enter image description here

enter image description here

I wonder if there is any way to solve this problem. This problem does not affect the normal compilation and execution of the code, but it is very uncomfortable when writing code.

  • The code analysis in Visual Studio is actually using Clang. Apparently it sometimes disagrees on the code. Among the options are ignoring the warning, or turn Intellisense warnings off (select "Build Only" in the Error List panel).. – BoP Sep 05 '22 at 08:15
  • Thanks for your reply, I can really fix this by disabling all syntax error checking, but I need syntax error checking sometimes. I wonder if there's a better way. – gzhuhxz Sep 05 '22 at 09:07
  • 1
    `##__VA_ARGS__` is a gcc non-standard extension. The reason why it doesn't work in another compiler is because it's non-conforming C code. You can't use gcc non-standard extensions if you wish to write good, portable code. If in doubt, compile with `-std=c17 -pedantic-errors` to compile as conforming C - and then the code won't compile in gcc either. See https://stackoverflow.com/questions/52891546/what-does-va-args-mean – Lundin Sep 05 '22 at 09:20
  • 1
    Anyway, you really shouldn't be using variadic functions and macros if it can be avoided. It has been proven time and again that this is a horrible, broken part of C and should be avoided in any sound design. Use a pointer to a struct or similar instead. – Lundin Sep 05 '22 at 09:26
  • Thank you for your reply. Yes, I try not to use the variable argument list as much as possible. In fact, I want to use the variable argument list to implement some of the default arguments. Are there other implementations? – gzhuhxz Sep 05 '22 at 15:57

0 Answers0