В чем разница между __PRETTY_FUNCTION__, __FUNCTION__, __func__? - PullRequest
195 голосов
/ 08 декабря 2010

В чем разница между __PRETTY_FUNCTION__, __FUNCTION__, __func__ и где они документированы?Как мне решить, какой из них использовать?

Ответы [ 5 ]

237 голосов
/ 08 декабря 2010

__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 «Имена функций в виде строк».

84 голосов
/ 13 ноября 2014

Несмотря на то, что он не полностью ответил на первоначальный вопрос, это, вероятно, то, что большинство людей, гуглявших в этом, хотели увидеть.

Для GCC:

petanb@debian:~$ cat test.cpp 
#include <iostream>

int main(int argc, char **argv)
{
    std::cout << __func__ << std::endl
              << __FUNCTION__ << std::endl
              << __PRETTY_FUNCTION__ << std::endl;
}
petanb@debian:~$ g++ test.cpp 
petanb@debian:~$ 
petanb@debian:~$ ./a.out 
main
main
int main(int, char**)
31 голосов

__PRETTY_FUNCTION__ обрабатывает функции C ++: классы, пространства имен, шаблоны и перегрузки

#include <iostream>

namespace N {
    class C {
        public:
            template <class T>
            static void f(int i) {
                std::cout << __func__ << std::endl
                          << __FUNCTION__ << std::endl
                          << __PRETTY_FUNCTION__ << std::endl;
            }
            template <class T>
            static void f(double f) {
                std::cout << __PRETTY_FUNCTION__ << std::endl;
            }
    };
}

int main() {
    N::C::f<char>(1);
    N::C::f<void>(1.0);
}

Вывод GCC 7.2 g++ -std=gnu++98:

f
f
static void N::C::f(int) [with T = char]
static void N::C::f(double) [with T = void]

Вы можететакже быть заинтересованным в трассировке стека с именами функций: стек вызовов печати в C или C ++

11 голосов
/ 08 декабря 2010

__func__ задокументировано в стандарте C ++ 0x в разделе 8.4.1.В данном случае это предопределенная локальная переменная функции в форме:

static const char __func__[] = "function-name ";

, где "имя функции" - это специфика реализации.Это означает, что всякий раз, когда вы объявляете функцию, компилятор неявно добавляет эту переменную в вашу функцию.То же самое относится к __FUNCTION__ и __PRETTY_FUNCTION__.Несмотря на их заглавные буквы, они не макросы.Хотя __func__ является дополнением к C ++, 0x

g++ -std=c++98 ....

все равно будет компилировать код, используя __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 ++ также содержит сигнатуру типа.

5 голосов
/ 02 августа 2017

Для тех, кому интересно, как это работает в VS.

MSVC 2015 Обновление 1, версия cl.exe 19.00.24215.1:

#include <iostream>

template<typename X, typename Y>
struct A
{
  template<typename Z>
  static void f()
  {
    std::cout << "from A::f():" << std::endl
      << __FUNCTION__ << std::endl
      << __func__ << std::endl
      << __FUNCSIG__ << std::endl;
  }
};

void main()
{
  std::cout << "from main():" << std::endl
    << __FUNCTION__ << std::endl
    << __func__ << std::endl
    << __FUNCSIG__ << std::endl << std::endl;

  A<int, float>::f<bool>();
}

вывод:

from main():
main
main
int __cdecl main(void)

from A::f():
A<int,float>::f
f
void __cdecl A<int,float>::f&ltbool>(void)

Использование __PRETTY_FUNCTION__ вызывает ошибку необъявленного идентификатора, как и ожидалось.

...