Существуют различные грязные приемы, в которых вы можете использовать различные макросы до определенного фиксированного числа. Однако правильное и правильное решение состоит в том, чтобы вообще не писать вариационный макрос. Намного лучше просто использовать
#define ASSERT_EXISTS(val, x) if (!x##_exists) { return error(#x " is missing", val); }
ASSERT_EXIST(100, a);
ASSERT_EXIST(100, b);
...
Или, что еще лучше, отбросьте все такие непристойные макросы в пользу удобочитаемого стандарта C.
if(!a_exists) { return error("a is missing", 100); }
if(!b_exists) { return error("b is missing", 100); }
if(!c_exists) { return error("c is missing", 100); }
Конечно, повторение кода - плохая практика, но секретные макроязыки - крайне плохая практика.