// RUN: cc -Wall -Wextra %s && ./a.out #include #if defined(__GNUC__) || defined(__clang__) // Supports 0-10 arguments #define VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N // ## deletes preceding comma if _VA_ARGS__ is empty (GCC, Clang) #define VA_NARGS(...) VA_NARGS_IMPL(_, ## __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) #else // Supports 1-10 arguments #define VA_NARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N #define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) #endif #define VA_NARGS2(...) ((int)(sizeof((int[]){ __VA_ARGS__ })/sizeof(int))) #define TEST(...) VA_NARGS(__VA_ARGS__) #define TEST2(...) VA_NARGS2(__VA_ARGS__) void test(void) { assert(TEST() == 0); assert(TEST(1) == 1); assert(TEST(1, 2) == 2); assert(TEST(1, 2, 3) == 3); assert(TEST(1, 2, 3, 'a') == 4); assert(TEST(1, 2, 3, 'a', 'b') == 5); assert(TEST(1, 2, 3, 'a', 'b', 'c') == 6); assert(TEST(1, 2, 3, 'a', 'b', 'c', 4.0) == 7); assert(TEST(1, 2, 3, 'a', 'b', 'c', 4.0, 5.0) == 8); assert(TEST(1, 2, 3, 'a', 'b', 'c', 4.0, 5.0, 6.0) == 9); assert(TEST(1, 2, 3, 'a', 'b', 'c', 4.0, 5.0, 6.0, 0) == 10); //assert(TEST(1, 2, 3, 'a', 'b', 'c', 4.0, 5.0, 6.0, 0, 0) == 11); // fails assert(TEST2() == 0); assert(TEST2(1) == 1); assert(TEST2(1, 2) == 2); assert(TEST2(1, 2, 3) == 3); assert(TEST2(1, 2, 3, 'a') == 4); assert(TEST2(1, 2, 3, 'a', 'b') == 5); assert(TEST2(1, 2, 3, 'a', 'b', 'c') == 6); assert(TEST2(1, 2, 3, 'a', 'b', 'c', 4.0) == 7); assert(TEST2(1, 2, 3, 'a', 'b', 'c', 4.0, 5.0) == 8); assert(TEST2(1, 2, 3, 'a', 'b', 'c', 4.0, 5.0, 6.0) == 9); assert(TEST2(1, 2, 3, 'a', 'b', 'c', 4.0, 5.0, 6.0, 0) == 10); assert(TEST2(1, 2, 3, 'a', 'b', 'c', 4.0, 5.0, 6.0, 0, 0) == 11); } int main(void) { test(); return 0; }