Если вы хотите положиться на первый аргумент, чтобы LogPrintf
был строковым литералом, тогда вы должны использовать конкатенацию строк для достижения своей цели:
// Assumes f_ always corresponds to a string literal:
#define LogPrintf(f_, ...) fprintf(stdout, "%s: " f_ "\n", __FUNCTION__, ##__VA_ARGS__)
Обратите внимание, однако,что в стандартном C макрос LogPrintf
требует как минимум двух аргументов, а ##
не имеет места.Я держу его здесь только потому, что вы используете его в своем исходном коде.
Однако если вы должны принимать строковые выражения формата, отличные от строковых литералов, тогда ваша самая простая альтернатива - выполнить несколько вызовов ввода-вывода в качестве другого ответа.также предлагает:
#define LogPrintf(f_, ...) do { \
fprintf(stdout, "%s: ", __FUNCTION__); \
fprintf(stdout, (f_), ##__VA_ARGS__); \
fputc('\n', stdout); \
} while (0)
Обратите внимание, что в этом случае макрос расширяется до оператора (без завершающей точки с запятой), тогда как в другом макрос расширяется до выражения .Если вы хотите получить возвращаемое значение (я) какой-либо из функций ввода-вывода, то в этом случае вам придется предусмотреть специальные условия для этого.
Если это также не работает для вас, токонечная альтернатива - написать и использовать вспомогательную функцию, как было предложено в комментариях:
#define LogPrintf(f_, ...) log_printf_impl(stdout, __FUNCTION__, (f_), ##__VA_ARGS__)
int log_printf_impl(FILE *f, const char *func, const char *fmt, ...) {
static const char prefix[] = "%s: ";
size_t flen = strlen(fmt);
va_list args;
int result = -1;
char *aug_fmt = malloc(sizeof(prefix) + strlen(fmt) + 1);
if (aug_fmt) {
va_start(args, fmt);
sprintf(aug_fmt, "%s%s\n", prefix, fmt);
result = vfprintf(f, aug_fmt, func, args);
va_end(args);
free(aug_fmt);
}
return result;
}