После небольшого исследования и много отвода о я придумал с этим:VARIADIC Функция Перегрузки в C
#include <stdio.h>
// Variadic Function Overloading:
#define VOID "__variadic_VOID__"
#define variadic_count(...) variadic_count_(__VA_ARGS__, 6, 5, 4, 3, 2, 1, 0)
#define variadic_count_(_6, _5, _4, _3, _2, _1, count, ...) count
#define variadic_token(func, ...) variadic_token_(func, variadic_count(__VA_ARGS__))
#define variadic_token_(func, count) variadic_token__(func, count)
#define variadic_token__(func, count) funC## _ ## count
#define variadic(func, ...)\
do {\
if (#__VA_ARGS__ == "\"__variadic_VOID__\"")\
{\
variadic_token__(func, 0)();\
}\
else\
{\
variadic_token(func, __VA_ARGS__)(__VA_ARGS__);\
}\
} while (0)
// Usage:
#define somefunction(...) variadic(somefunction, __VA_ARGS__)
#define somefunction_0()\
do {\
printf("somefunction_0(VOID)\n\n");\
} while (0)
#define somefunction_1(x)\
do {\
printf("somefunction_1(x = %i)\n\n", (x));\
} while (0)
#define somefunction_2(x, y)\
do {\
printf("somefunction_2(x = %i, y = %i)\n\n", (x), (y));\
} while (0)
int main(int argc, char* argv[])
{
//somefunction(); ERROR
somefunction(VOID);
somefunction(1);
somefunction(11);
somefunction(2, 3);
//somefunction(1, 2, 3); ERROR
printf("\n\n");
return 0;
}
По существу, это позволяет проводить различие между нулем и единицей аргументами через специальный знак VOID. Он работает, если переменная function/macro не передается строковым литералом, определенным VOID, в качестве единственного аргумента. В этом случае только вызов somefunction("__variadic_VOID__");
вызовет неожиданное поведение; передавая переменную с тем же значением, что и строковый литерал, не вызывает неожиданного поведения.
Хотя предоставленный код работает только для аргументов 0-6, его можно модифицировать для работы с большим количеством аргументов.
Мне любопытно, однако, что if ("blah" == "blah") {doSomething();}
оптимизирован для doSomething();
компилятором (Pelles C)? Или сравнение указателей происходит во время выполнения? Если он оптимизирован, то я думаю, что этот фрагмент кода позволяет легко и эффективно переадресации функций/макросов ... это правильно?
Вы не можете использовать '==' для сравнения строк, он будет сравнивать указатели * с строками, а не с фактическими строками. –
@JoachimPileborg Я протестировал код, указанный выше, и он работает; в этом случае сравнение выполняется между двумя строковыми литералами. – sweetname
Равные строковые литералы могут совместно использовать хранилище, но не обязательно. Если две строки сравниваются с '==', они равны с 'strcmp', но это не так наоборот. Например, в 'char foo [] =" blah "; foo == "blah"; ', сравнение гарантированно будет ложным. – mafso