Skip to content

Instantly share code, notes, and snippets.

@christophercrouzet
Created September 14, 2019 02:15
Show Gist options
  • Save christophercrouzet/403548e3f703425c5bcc235d23bdbb7b to your computer and use it in GitHub Desktop.
Save christophercrouzet/403548e3f703425c5bcc235d23bdbb7b to your computer and use it in GitHub Desktop.
Counting Variadic Macro Arguments in C99 and C++
/*
Credits: Jens Gustedt
https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments
*/
#include <stdio.h>
#define EXPAND(x) x
#define CONCAT_(a, b) a##b
#define CONCAT(a, b) CONCAT_(a, b)
#define IF_0(t, f) f
#define IF_1(t, f) t
#define IF(x, t, f) CONCAT(IF_, x)(t, f)
#define ARG( \
_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, ...) _64
#define IS_EMPTY_TRIGGER(...) ,
#define IS_EMPTY_HAS_COMMA(...) \
EXPAND(ARG( \
__VA_ARGS__, \
1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 0))
#define IS_EMPTY_PASTE(_0, _1, _2, _3, _4) _0##_1##_2##_3##_4
#define IS_EMPTY_0000 0
#define IS_EMPTY_0001 1
#define IS_EMPTY_0010 0
#define IS_EMPTY_0011 0
#define IS_EMPTY_0100 0
#define IS_EMPTY_0101 0
#define IS_EMPTY_0110 0
#define IS_EMPTY_0111 0
#define IS_EMPTY_1000 0
#define IS_EMPTY_1001 0
#define IS_EMPTY_1010 0
#define IS_EMPTY_1011 0
#define IS_EMPTY_1100 0
#define IS_EMPTY_1101 0
#define IS_EMPTY_1110 0
#define IS_EMPTY_1111 0
#define IS_EMPTY_(_0, _1, _2, _3) \
IS_EMPTY_PASTE(IS_EMPTY_, _0, _1, _2, _3)
#define IS_EMPTY(...) \
IS_EMPTY_( \
IS_EMPTY_HAS_COMMA(__VA_ARGS__), \
IS_EMPTY_HAS_COMMA(IS_EMPTY_TRIGGER __VA_ARGS__), \
IS_EMPTY_HAS_COMMA(__VA_ARGS__ ()), \
IS_EMPTY_HAS_COMMA(IS_EMPTY_TRIGGER __VA_ARGS__ ()))
#define COUNT_ARGS_(...) \
EXPAND(ARG( \
__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 COUNT_ARGS(...) \
IF(IS_EMPTY(__VA_ARGS__), 0, COUNT_ARGS_(__VA_ARGS__))
static const int count_0 = COUNT_ARGS();
static const int count_1 = COUNT_ARGS(a);
static const int count_8 = COUNT_ARGS(a, b, c, d, e, f, g, h);
int
main(void)
{
printf("count_0: %d\n", count_0);
printf("count_1: %d\n", count_1);
printf("count_8: %d\n", count_8);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment