wake-up-neo.com

Was ist der Unterschied zwischen __PRETTY_FUNCTION__, __FUNCTION__, __func__?

Was ist der Unterschied zwischen __PRETTY_FUNCTION__, __FUNCTION__, __func__, und wo sind sie dokumentiert? Wie entscheide ich mich für eine?

197
Matt Joiner

__func__ Ist ein implizit deklarierter Bezeichner, der zu einer Zeichenarrayvariablen mit dem Funktionsnamen erweitert wird, wenn er in einer Funktion verwendet wird. Es wurde C in C99 hinzugefügt. Von C99 §6.4.2.2/1:

Der Bezeichner __func__ Wird vom Übersetzer implizit so deklariert, als ob unmittelbar nach der öffnenden Klammer jeder Funktionsdefinition die Deklaration

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

erschienen, wobei Funktionsname der Name der lexikalisch einschließenden Funktion ist. Dieser Name ist der schmucklose Name der Funktion.

Beachten Sie, dass es sich nicht um ein Makro handelt und während der Vorverarbeitung keine besondere Bedeutung hat.

__func__ Wurde C++ in C++ 11 hinzugefügt, wo angegeben wird, dass es "eine implementierungsdefinierte Zeichenfolge" enthält (C++ 11 §8.4.1 [dcl.fct.def.general]/8). , was nicht ganz so nützlich ist wie die Spezifikation in C. (Der ursprüngliche Vorschlag, __func__ zu C++ hinzuzufügen, war N1642 ).

__FUNCTION__ Ist eine Pre-Standard-Erweiterung, die einige C-Compiler unterstützen (einschließlich gcc und Visual C++). Im Allgemeinen sollten Sie __func__ verwenden, wenn dies unterstützt wird, und nur __FUNCTION__, wenn Sie einen Compiler verwenden, der dies nicht unterstützt (z. B. Visual C++, der C99 nicht unterstützt und dies tut) unterstützt noch nicht alle C++ 0x, liefert keine __func__).

__PRETTY_FUNCTION__ Ist eine gcc-Erweiterung, die größtenteils mit __FUNCTION__ Identisch ist, außer dass sie für C++ - Funktionen den "hübschen" Namen der Funktion einschließlich der Signatur der Funktion enthält. Visual C++ hat eine ähnliche (aber nicht ganz identische) Erweiterung, __FUNCSIG__.

Informationen zu nicht standardmäßigen Makros finden Sie in der Dokumentation Ihres Compilers. Die Visual C++ - Erweiterungen sind in der MSDN-Dokumentation des C++ - Compilers enthalten "Predefined Macros" . Die Erweiterungen der gcc-Dokumentation werden auf der Seite der gcc-Dokumentation "Funktionsnamen als Zeichenfolgen" beschrieben

240
James McNellis

Obwohl die ursprüngliche Frage nicht vollständig beantwortet wurde, ist dies wahrscheinlich das, was die meisten Googler sehen wollten.

Für GCC:

[email protected]:~$ cat test.cpp 
#include <iostream>

int main(int argc, char **argv)
{
    std::cout << __func__ << std::endl
              << __FUNCTION__ << std::endl
              << __PRETTY_FUNCTION__ << std::endl;
}
[email protected]:~$ g++ test.cpp 
[email protected]:~$ 
[email protected]:~$ ./a.out 
main
main
int main(int, char**)
88
Petr

__PRETTY_FUNCTION__ verarbeitet C++ - Funktionen: Klassen, Namespaces, Vorlagen und Überladung

#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);
}

Ausgang 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]

Möglicherweise interessieren Sie sich auch für Stack-Traces mit Funktionsnamen: print call stack in C oder C++

C++ 20 source_location::function_name

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1208r5.pdf ist zu C++ 20 übergegangen, wir haben also noch eine andere Möglichkeit es.

In der Dokumentation heißt es:

constexpr const char * Funktionsname () const noexcept;

6 Rückgabe: Wenn dieses Objekt eine Position im Hauptteil einer Funktion darstellt, wird ein implementierungsdefiniertes NTBS zurückgegeben, das dem Funktionsnamen entsprechen sollte. Andernfalls wird eine leere Zeichenfolge zurückgegeben.

dabei bedeutet NTBS "Null Terminated Byte String".

Ich werde es versuchen, wenn GCC unterstützt wird, GCC 9.1.0 mit g++-9 -std=c++2a unterstützt es immer noch nicht.

__func__ ist im C++ 0x-Standard in Abschnitt 8.4.1 dokumentiert. In diesem Fall handelt es sich um eine vordefinierte lokale Funktionsvariable des Formulars:

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

dabei ist "Funktionsname" implementierungsspezifisch. Dies bedeutet, dass der Compiler diese Variable implizit zu Ihrer Funktion hinzufügt, wenn Sie eine Funktion deklarieren. Gleiches gilt für __FUNCTION__ und __PRETTY_FUNCTION__. Trotz ihrer Großschreibung sind sie keine Makros. Obwohl __func__ ist eine Ergänzung zu C++ 0x

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

kompiliert weiterhin Code mit __func__.

__PRETTY_FUNCTION__ und __FUNCTION__ sind hier dokumentiert http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Function-Names.html#Function-Names . __FUNCTION__ ist nur ein anderer Name für __func__. __PRETTY_FUNCTION__ ist das gleiche wie __func__ in C, aber in C++ enthält es auch die Typensignatur.

12
sashang

Für diejenigen, die sich fragen, wie es in VS geht.

MSVC 2015 Update 1, cl.exe Version 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>();
}

ausgabe:

 von main (): 
 main 
 main 
 int __cdecl main (void) 
 
 von A :: f () : 
 A <int, float> :: f 
 F 
 Void __cdecl A <int, float> :: f & ltbool> (void) 

Verwendung von __PRETTY_FUNCTION__ löst erwartungsgemäß einen nicht deklarierten Bezeichnerfehler aus.

5
finnan