__func__ или __FUNCTION__ или ручной const char * id?
Мне интересно, насколько широко __func__
(часть C99, но я компилирую как C89) и __FUNCTION__
.
У меня есть старая база кода, которая в основном использует ручные переменные const char* id;
, которые затем передаются в различные (в основном, протоколирующие) функции. Я хотел бы избавиться от этого и переместить имя функции в макрос.
Ответы
Ответ 1
Заголовок boost current_function.hpp содержит несколько #define
для способов получения текущей функции на разных платформах.
Это не означает, что эти платформы не поддерживают другие способы получения текущей функции, но выбор, сделанный для повышения, скорее всего, будет представлять собой приятные (если не самые лучшие) способы получения информации на этих платформах.
Адаптация этого заголовка для вашего кода (и для C) вполне может быть тем, что вам нужно.
Ответ 2
Предопределенный идентификатор __func__
был добавлен к стандарту ISO ISO 1999; у старого стандарта 1990 C его нет.
Поддержка __func__
в компиляторах pre-C99 будет зависеть от того, какой компилятор вы используете.
Современные версии поддержки gcc __func__
даже в режиме C90 (-ansi
или -std=c89
).
До стандарта __func__
был добавлен стандарт, gcc реализовал собственное эквивалентное расширение, но с именем __FUNCTION__
. (gcc также поддерживает __PRETTY_FUNCTION__
, который идентичен __func__
и __FUNCTION__
для C, но предоставляет дополнительную информацию на С++.)
Руководство gcc дает несколько советов:
__FUNCTION__
- это другое имя для __func__
. Старые версии GCC распознают только это имя. Однако это не стандартизировано. Для максимальной переносимости, мы рекомендуем использовать __func__
, но предоставить резервную копию с препроцессором:
#if __STDC_VERSION__ < 199901L
# if __GNUC__ >= 2
# define __func__ __FUNCTION__
# else
# define __func__ "<unknown>"
# endif
#endif
что означает, что gcc добавила поддержку для __FUNCTION__
в версии 2. gcc 2.0 был выпущен в 1992 году; вы вряд ли будете использовать версию gcc, которая не поддерживает как минимум __FUNCTION__
, если не __func__
.
Обратите внимание, что поскольку __func__
и __FUNCTION__
являются предопределенными идентификаторами, а не макросами, вам нужен только #define
один раз, а не в каждой функции. С другой стороны, вы не можете использовать #ifdef __func__
или #ifdef __FUNCTION__
для определения уровня поддержки.
Как и для других компиляторов, быстрый эксперимент показывает, что Microsoft Visual С++ 2010 Express поддерживает __FUNCTION__
, но не __func__
или __PRETTY_FUNCTION__
при компиляции кода C. Вышеупомянутый блок кода из руководства gcc компилируется под MSVC, но в результате он __func__
определяется как "<unknown>"
. Не должно быть слишком сложно настроить его, чтобы распознать, что MSVC поддерживает __FUNCTION__
. (Я не знаю, делают ли это более старые версии.) Для этого вы, вероятно, можете использовать предопределенный макрос _MSC_VER
. Документация Microsoft говорит, что поддержка __FUNCTION__
восходит по крайней мере к выпуску 2003 года, который устанавливает _MSC_VER
в 1300
, поэтому изменение второй строки на
# if __GNUC >= 2 || _MSC_VER >= 1300
- хорошее начало. (Возможно, это было поддержано в более ранних версиях.)
Для компиляторов, отличных от gcc и MSVC, вам нужно будет проконсультироваться со своей соответствующей документацией, но в любом случае блок кода, рекомендованный в руководстве gcc, должен работать для любого компилятора, в худшем случае возвращается к "<unknown>"
.
Ответ 3
Я считаю, что это независимо от того, какой стандарт C используется (если C89 или C99). Более важным фактором является использование компилятора, поскольку он реализует __func__
. Последние компиляторы GCC добавят __func__
независимо от используемого стандарта. Я думаю.:)