Jaka jest różnica między funkcją, funkcją, func?
Jaka jest różnica między __PRETTY_FUNCTION__
, __FUNCTION__
, __func__
, a gdzie są udokumentowane? Jak zdecydować, którego z nich użyć?
5 answers
__func__
jest niejawnie zadeklarowanym identyfikatorem, który rozszerza 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 niejawnie deklarowany przez tłumacza, tak jakby bezpośrednio po nawiasie otwierającym każdej definicji funkcji deklaracjastatic const char __func__[] = "function-name";
Pojawił się, gdzie function-name jest nazwą funkcji leksykalnie zamykającej. To nazwa jest nienadorowaną nazwą funkcji.
Zauważ, że nie jest to makro i nie ma specjalnego znaczenia podczas wstępnego przetwarzania.
__func__
został dodany do C++ w C++11, gdzie jest określony jako zawierający "łańcuch zdefiniowany w implementacji"(C++11 §8.4.1 [dcl.fct.def.ogólna] / 8), która nie jest tak przydatna jak specyfikacja w C. (pierwotna propozycja dodania __func__
do C++ to N1642 ).
__FUNCTION__
jest pre-standardowym rozszerzeniem, które niektóre kompilatory C obsługują (w tym GCC i Visual C++); ogólnie rzecz biorąc, powinieneś używać __func__
Gdzie jest on obsługiwany i używać __FUNCTION__
tylko jeśli 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 wszystkich C++0x, nie dostarcza __func__
).
__PRETTY_FUNCTION__
jest rozszerzeniem gcc, które jest w większości takie samo jak __FUNCTION__
, z tym wyjątkiem, że dla funkcji C++ zawiera "ładną" nazwę funkcji łącznie z podpisem funkcji. Visual C++ ma podobny (ale nie całkiem identyczne) rozszerzenie, __FUNCSIG__
.
W przypadku niestandardowych makr, należy zapoznać się z dokumentacją kompilatora. Rozszerzenia Visual C++ są zawarte w dokumentacji MSDN kompilatora "predefiniowanych makr". Rozszerzenia dokumentacji gcc są opisane na stronie dokumentacji gcc " nazwy funkcji jako ciągi znaków."
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55
Pomimo Nie pełnej odpowiedzi na pierwotne pytanie, to jest prawdopodobnie to, co większość ludzi googlujących to chciał zobaczyć.
Dla GCC:
$ cat test.cpp
#include <iostream>
int main(int argc, char **argv)
{
std::cout << __func__ << std::endl
<< __FUNCTION__ << std::endl
<< __PRETTY_FUNCTION__ << std::endl;
}
$ g++ test.cpp
$ ./a.out
main
main
int main(int, char**)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-10 07:07:58
__PRETTY_FUNCTION__
obsługuje funkcje C++: klasy, przestrzenie nazw, szablony i przeciążenia
Main.cpp
#include <iostream>
namespace N {
class C {
public:
template <class T>
static void f(int i) {
(void)i;
std::cout << "__func__ " << __func__ << std::endl
<< "__FUNCTION__ " << __FUNCTION__ << std::endl
<< "__PRETTY_FUNCTION__ " << __PRETTY_FUNCTION__ << std::endl;
}
template <class T>
static void f(double f) {
(void)f;
std::cout << "__PRETTY_FUNCTION__ " << __PRETTY_FUNCTION__ << std::endl;
}
};
}
int main() {
N::C::f<char>(1);
N::C::f<void>(1.0);
}
Skompiluj i uruchom:
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
Wyjście:
__func__ f
__FUNCTION__ f
__PRETTY_FUNCTION__ static void N::C::f(int) [with T = char]
__PRETTY_FUNCTION__ static void N::C::f(double) [with T = void]
Możesz być również zainteresowany śladami stosu z nazwami funkcji: Drukuj 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 poszedł do C++20, więc mamy jeszcze inny sposób.
Dokumentacja mówi:
Constexpr const char * function_name () const noexcept;
6 zwraca: jeśli obiekt ten reprezentuje pozycję w ciele funkcji, zwraca zdefiniowane w implementacji NTB, które powinny odpowiadać nazwa funkcji. W przeciwnym razie zwraca pusty łańcuch.
Gdzie NTBS oznacza "null zakończony Łańcuch bajtowy".
Spróbuję kiedy wsparcie dotrze do GCC, GCC 9.1.0 z g++-9 -std=c++2a
nadal nie wesprzyj to.
Https://en.cppreference.com/w/cpp/utility/source_location claims usage will be like:
#include <iostream>
#include <string_view>
#include <source_location>
void log(std::string_view message,
const std::source_location& location std::source_location::current()
) {
std::cout << "info:"
<< location.file_name() << ":"
<< location.line() << ":"
<< location.function_name() << " "
<< message << '\n';
}
int main() {
log("Hello world!");
}
Możliwe wyjście:
info:main.cpp:16:main Hello world!
Więc zauważ, jak to zwraca informacje o wywołującym i dlatego jest idealne do użycia w logowaniu, Zobacz także: czy istnieje sposób, aby uzyskać nazwę funkcji wewnątrz funkcji C++?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-14 14:55:36
__func__
jest udokumentowany w standardzie C++0x w sekcji 8.4.1. W tym przypadku jest to predefiniowana zmienna lokalna funkcji o postaci:
static const char __func__[] = "function-name ";
Gdzie" nazwa funkcji " jest implementacją specfic. 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__
. Pomimo wielkich liter, nie są to makra. Chociaż {[2] } jest dodatkiem do C++0x
g++ -std=c++98 ....
Będzie nadal kompilować kod używając __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 tylko inna nazwa __func__
. __PRETTY_FUNCTION__
jest tym samym co __func__
W C, ale w C++ zawiera również sygnaturę typu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-08 09:14:55
Dla tych, którzy zastanawiają się, jak to idzie w VS.
MSVC 2015 Update 1, cl.wersja 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>();
}
Wyjście:
from main(): main main int __cdecl main(void) from A::f(): A<int,float>::f f void __cdecl A<int,float>::f<bool>(void)
Użycie __PRETTY_FUNCTION__
powoduje, zgodnie z oczekiwaniami, nierejestrowany błąd identyfikatora.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-02 15:21:37