Использование и возврат вывода в макросе C
Я пытаюсь обработать некоторый код, чтобы ловить и печатать сообщения об ошибках. В настоящее время я использую макрос, например:
#define my_function(x) \
switch(function(x)) { \
case ERROR: \
fprintf(stderr, "Error!\n"); \
break; \
}
Обычно я никогда не записываю вывод функции, и это работает нормально. Но я нашел пару случаев, когда мне также нужно вернуть значение function()
. Я пробовал что-то вроде следующего, но это приводит к синтаксической ошибке.
#define my_function(x) \
do { \
int __err = function(x); \
switch(__err) { \
case ERROR: \
fprintf(stderr, "Error!\n"); \
break; \
} \
__err; \
} while(0)
Я могу объявить глобальную переменную для хранения возвращаемого значения функции, но это выглядит уродливым, и моя программа многопоточна, что может вызвать проблемы. Я надеюсь, что там будет лучшее решение.
Ответы
Ответ 1
Это относительно сложный код, в мастере не так много причин. Сделайте это inline
(C99) или static
(C89) или оба, если вы действительно хотите поместить его в файл заголовка. С любым разумным компилятором это должно привести к той же эффективности, что и макрос.
Ответ 2
GCC имеет функцию под названием оператор выражения
Так что, если определить макрос как
#define FOO(A) ({int retval; retval = do_something(A); retval;})
тогда вы сможете использовать его как
foo = FOO(bar);
Ответ 3
Очень поздний ответ. Но тем не менее. Я согласен, что встроенные функции лучше, но MACROs предлагают довольно приятную печать, которую вы не можете получить с встроенными функциями. Я согласен с @qrdl, что вы действительно можете использовать выражения выражения, если бы вы немного изменили свои утверждения. Вот как это будет работать с макросом -
#define my_function(x, y) ({ \
int __err = 0; \
do { \
__err = function(x, y); \
switch(__err) { \
case ERROR: \
fprintf(stderr, "Error!\n"); \
break; \
} \
} while(0); \
__err; \
})
Ответ 4
Извините, это редактирование...
- Думаю, вам просто нужны фигурные скобки. Нет необходимости в ключах do..while.
- Убедитесь, что обратная косая черта - последние символы в каждой строке (без пробелов).
- Если вам нужно получить значение err из макроса, вы можете просто добавить параметр
Так же:
#define my_function(x, out) \
{ \
int __err = function(x); \
switch(__err) { \
case ERROR: \
fprintf(stderr, "Error!\n"); \
break; \
} \
__err; \
(*(out)) = _err; \
}
Чтобы сохранить парадигму C-pass-by-reference, вы должны вызвать my_function следующим образом:
int output_err;
my_function(num, &output_err);
Таким образом, если вы решите сделать my_function реальную функцию, вам не нужно менять ссылки на вызовы.
Btw, qrdl "Выражения выписки" также являются хорошим способом сделать это.
Ответ 5
В вашем втором выражении (строки 2 и 3) есть 2 недостающих \, это правильно?
Ответ 6
нет необходимости объявлять переменную, если ваша функция возвращает что-то, тогда вы можете напрямую получить это значение. Например:
#define FOO(A) do_something(A)
Здесь do_something возвращает некоторое целое число. Затем вы можете легко использовать его, например:
int a = FOO(a);