Jaka jest różnica między __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
, i gdzie są one udokumentowane? Jak zdecydować, którego użyć?
źródło
Jaka jest różnica między __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
, i gdzie są one udokumentowane? Jak zdecydować, którego użyć?
__func__
jest niejawnie zadeklarowanym identyfikatorem, który rozwija się do zmiennej tablicy znaków zawierającej nazwę funkcji, gdy jest używana wewnątrz funkcji. Został dodany do C w C99. Od C99 §6.4.2.2 / 1:
Identyfikator
__func__
jest domyślnie zadeklarowany przez tłumacza, tak jakby deklaracja znajdowała się bezpośrednio po nawiasie otwierającym każdej definicji funkcjistatic const char __func__[] = "function-name";
pojawił się, gdzie nazwa-funkcji jest nazwą funkcji zamykającej leksykalnie. Ta nazwa jest nie ozdobioną nazwą funkcji.
Należy pamiętać, że nie jest to makro i nie ma specjalnego znaczenia podczas przetwarzania wstępnego.
__func__
został dodany do C ++ w C ++ 11, gdzie jest określony jako zawierający „ciąg zdefiniowany w implementacji” (C ++ 11 §8.4.1 [dcl.fct.def.general] / 8), co nie jest tak bardzo użyteczne jako specyfikacja w C. (Oryginalna propozycja dodania __func__
do C ++ to N1642 ).
__FUNCTION__
jest standardowym rozszerzeniem obsługiwanym przez niektóre kompilatory C (w tym gcc i Visual C ++); ogólnie powinieneś używać __func__
tam, gdzie jest obsługiwany i używać tylko __FUNCTION__
wtedy, gdy używasz kompilatora, który go nie obsługuje (na przykład Visual C ++, który nie obsługuje C99 i nie obsługuje jeszcze całego C ++ 0x, nie zapewnić __func__
).
__PRETTY_FUNCTION__
jest rozszerzeniem gcc, które jest w większości takie samo __FUNCTION__
, z wyjątkiem tego, że dla funkcji C ++ zawiera „ładną” nazwę funkcji, w tym podpis funkcji. Visual C ++ ma podobne (ale nie do końca identyczne) rozszerzenie,__FUNCSIG__
.
W przypadku niestandardowych makr warto zajrzeć do dokumentacji kompilatora. Rozszerzenia Visual C ++ są zawarte w dokumentacji MSDN kompilatora C ++ „Predefiniowane makra” . Rozszerzenia dokumentacji gcc są opisane na stronie dokumentacji gcc „Nazwy funkcji jako ciągi znaków”.
__FUNCTION__
, robią nieco inne rzeczy. gcc daje równowartość__func__
. VC podaje nieudekorowaną, ale wciąż ozdobioną wersję nazwy. W przypadku metody o nazwie „foo”, gcc da ci"foo"
, VC da"my_namespace::my_class::foo"
.__PRETTY_FUNCTION__
, pojawia się na liście jako dostępny, a kiedy na nim przesunę kursor myszy, wyświetla informacje o nazwie funkcji, jednak nie kompiluje się.Mimo, że nie udało się w pełni odpowiedzieć na pierwotne pytanie, prawdopodobnie właśnie to chciało zobaczyć większość osób odwiedzających google.
W przypadku GCC:
źródło
__func__
działa, gdy jest osadzony w innej funkcji? Powiedzmy, że mam funkcję1, nie wymaga żadnych argumentów. funkcja 1 wywołuje funkcję 2, która obejmuje__func__
, która nazwa funkcji zostanie wydrukowana, 1 czy 2?__func__
to makro, to tłumaczy na dowolną funkcję, w której się obecnie znajdujesz. Jeśli umieścisz go w f1 i wywołasz f1 w f2, zawsze dostaniesz f1.__PRETTY_FUNCTION__
obsługuje funkcje C ++: klasy, przestrzenie nazw, szablony i przeciążeniemain.cpp
Skompiluj i uruchom:
Wynik:
Mogą Cię również zainteresować ślady stosu z nazwami funkcji: wydrukuj stos wywołań w C lub C ++
Testowane w 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 przeszedł do C ++ 20, więc mamy jeszcze inny sposób, aby to zrobić.
Dokumentacja mówi:
gdzie NTBS oznacza „Ciąg bajtów zakończony zerem”.
Spróbuję, kiedy wsparcie dotrze do GCC, GCC 9.1.0
g++-9 -std=c++2a
nadal go nie obsługuje.https://en.cppreference.com/w/cpp/utility/source_location roszczenia będą wyglądać następująco:
Możliwe wyjście:
więc zwróć uwagę, jak to zwraca informacje o dzwoniącym, a zatem idealnie nadaje się do użycia przy logowaniu, zobacz także: Czy istnieje sposób na uzyskanie nazwy funkcji wewnątrz funkcji C ++?
źródło
__func__
jest udokumentowane w standardzie C ++ 0x w sekcji 8.4.1. W tym przypadku jest to predefiniowana lokalna zmienna funkcji w formie:gdzie „nazwa funkcji” jest specyficzna dla implementacji. Oznacza to, że za każdym razem, gdy deklarujesz funkcję, kompilator doda tę zmienną niejawnie do twojej funkcji. To samo dotyczy
__FUNCTION__
i__PRETTY_FUNCTION__
. Mimo górnej części nie są makrami. Chociaż__func__
jest dodatkiem do C ++ 0xnadal będzie kompilować kod za pomocą
__func__
.__PRETTY_FUNCTION__
i__FUNCTION__
są udokumentowane tutaj http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Function-Names.html#Function-Names .__FUNCTION__
to po prostu inna nazwa dla__func__
.__PRETTY_FUNCTION__
jest taki sam jak__func__
w C, ale w C ++ zawiera również podpis typu.źródło
__func__
nie jest częścią C ++ 03. Został dodany w C ++ 0x, ale C ++ 0x nie jest jeszcze „standardem C ++”, ale nadal jest w wersji roboczej.Dla tych, którzy zastanawiają się, jak to wygląda w VS.
MSVC 2015 Update 1, cl.exe wersja 19.00.24215.1:
wynik:
Korzystanie z
__PRETTY_FUNCTION__
wyzwalaczy niezadeklarowany błąd identyfikatora, zgodnie z oczekiwaniami.źródło