В чем разница между __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
и где они зарегистрированы? Как мне решить, какой использовать?
источник
В чем разница между __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
и где они зарегистрированы? Как мне решить, какой использовать?
__func__
является неявно объявленным идентификатором, который расширяется до переменной массива символов, содержащей имя функции, когда он используется внутри функции. Он был добавлен в C в C99. От C99 §6.4.2.2 / 1:
Идентификатор
__func__
неявно объявляется транслятором, как если бы, сразу после открывающей скобки каждого определения функции, объявлениеstatic const char __func__[] = "function-name";
где имя-функции - это имя лексической функции. Это имя является неукрашенным именем функции.
Обратите внимание, что это не макрос, и он не имеет особого значения во время предварительной обработки.
__func__
был добавлен в C ++ в C ++ 11, где он указан как содержащий «строку, определяемую реализацией» (C ++ 11 §8.4.1 [dcl.fct.def.general] / 8), что не совсем полезно в качестве спецификации в C. (Первоначальное предложение добавить __func__
в C ++ было N1642 ).
__FUNCTION__
это стандартное расширение, которое поддерживают некоторые компиляторы C (включая gcc и Visual C ++); в общем, вы должны использовать __func__
там, где это поддерживается, и использовать только в том __FUNCTION__
случае, если вы используете компилятор, который его не поддерживает (например, Visual C ++, который не поддерживает C99 и еще не поддерживает весь C ++ 0x, не предоставить __func__
).
__PRETTY_FUNCTION__
является расширением gcc, которое по большей части совпадает с тем __FUNCTION__
, за исключением того, что для функций C ++ оно содержит «красивое» имя функции, включая сигнатуру функции. Visual C ++ имеет похожее (но не совсем идентичное) расширение __FUNCSIG__
.
Что касается нестандартных макросов, вы можете обратиться к документации вашего компилятора. Расширения Visual C ++ включены в документацию MSDN «Предопределенных макросов» компилятора C ++ . Расширения документации gcc описаны на странице документации gcc «Имена функций в виде строк».
__FUNCTION__
, они делают немного разные вещи. GCC дает эквивалент__func__
. VC дает неукрашенную, но все еще украшенную версию названия. Для метода с именем "foo", gcc даст вам"foo"
, VC даст"my_namespace::my_class::foo"
.__PRETTY_FUNCTION__
он отображается в списке как доступный, и когда я наведу на него курсор мыши, он отображает информацию о названии функции, но не компилируется.Несмотря на то, что он не полностью ответил на первоначальный вопрос, это, вероятно, то, что большинство людей, гуглявших, хотели увидеть.
Для GCC:
источник
__func__
он, когда он встроен в другую функцию? Допустим, у меня есть function1, она не принимает аргументов. function1 вызывает function2, которая включает__func__
, какое имя функции будет напечатано, 1 или 2?__func__
это макрос, он будет транслироваться в любую функцию, в которой вы сейчас находитесь. Если вы поместите его в f1 и вызовете f1 в f2, вы всегда получите f1.__PRETTY_FUNCTION__
обрабатывает функции C ++: классы, пространства имен, шаблоны и перегрузкиmain.cpp
Скомпилируйте и запустите:
Вывод:
Вас также могут заинтересовать трассировки стека с именами функций: стек вызовов печати в C или C ++
Протестировано в Ubuntu 19.04, GCC 8.3.0.
C ++ 20
std::source_location::function_name
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1208r5.pdf попал в C ++ 20, поэтому у нас есть еще один способ сделать это.
Документация гласит:
где NTBS означает «строка байтов, завершенная нулем».
Я попробую, когда поддержка придет в GCC, GCC 9.1.0
g++-9 -std=c++2a
все еще не поддерживает его.https://en.cppreference.com/w/cpp/utility/source_location утверждает, что использование будет следующим:
Возможный вывод:
так что обратите внимание, как это возвращает информацию о вызывающем абоненте и, следовательно, идеально подходит для использования при ведении журнала, см. также: Есть ли способ получить имя функции внутри функции C ++?
источник
__func__
задокументировано в стандарте C ++ 0x в разделе 8.4.1. В данном случае это предопределенная локальная переменная функции вида:где «имя функции» - это специфика реализации. Это означает, что всякий раз, когда вы объявляете функцию, компилятор неявно добавляет эту переменную в вашу функцию. То же самое верно
__FUNCTION__
и для__PRETTY_FUNCTION__
. Несмотря на их заглавные буквы, они не макросы. Хотя__func__
это дополнение к C ++ 0xбудет по-прежнему компилировать код, используя
__func__
.__PRETTY_FUNCTION__
и__FUNCTION__
задокументированы здесь http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Function-Names.html#Function-Names .__FUNCTION__
это просто другое имя для__func__
.__PRETTY_FUNCTION__
такой же, как__func__
в C, но в C ++ он также содержит сигнатуру типа.источник
__func__
не является частью C ++ 03. Он был добавлен в C ++ 0x, но C ++ 0x еще не является «стандартом C ++», он все еще находится в черновом варианте.Для тех, кто интересуется, как это происходит в VS.
MSVC 2015 обновление 1, версия cl.exe 19.00.24215.1:
вывод:
Использование
__PRETTY_FUNCTION__
триггеров необъявленной ошибки идентификатора, как и ожидалось.источник