__PRETTY_FUNCTION__, __FUNCTION__, __func__의 차이점은 무엇입니까? 무엇인가 __PRETTY_FUNCTION__, __FUNCTION__,

사이의 차이가 무엇인가 __PRETTY_FUNCTION__, __FUNCTION__, __func__, 그리고 그들이 어디에 문서화는? 사용할 것을 어떻게 결정합니까?



답변

__func__함수 내에서 사용될 때 함수 이름을 포함하는 문자 배열 변수로 확장되는 암시 적으로 선언 된 식별자입니다. C99에서 C에 추가되었습니다. 에서 C99 / 1 §6.4.2.2 :

식별자 __func__는 마치 각 함수 정의의 여는 중괄호 바로 뒤에 선언처럼 마치 번역자에 의해 암시 적으로 선언됩니다.

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

여기서 function-name은 어휘 포함 함수의 이름입니다. 이 이름은 기능의 이름이 지정되지 않은 이름입니다.

매크로가 아니며 전처리 과정에서 특별한 의미가 없습니다.

__func__C ++ 11의 C ++에 추가되었으며, “구현 정의 문자열”(C ++ 11 §8.4.1 [dcl.fct.def.general] / 8)을 포함하는 것으로 지정되었습니다. C의 스펙으로 유용합니다 ( __func__C ++에 추가 할 원래 제안 은 N1642였습니다 ).

__FUNCTION__일부 C 컴파일러가 지원하는 사전 표준 확장입니다 (gcc 및 Visual C ++ 포함). 일반적으로 __func__지원되는 위치 를 사용해야 하며 지원 __FUNCTION__하지 않는 컴파일러를 사용하는 경우 에만 사용해야 합니다 (예 : C99를 지원하지 않고 C ++ 0x를 모두 지원하지 않는 Visual C ++는 지원하지 않습니다) 제공 __func__).

__PRETTY_FUNCTION____FUNCTION__C ++ 함수의 경우 함수의 서명을 포함하여 함수의 “예쁜”이름을 포함한다는 점을 제외하고 는 대부분과 동일한 gcc 확장입니다 . Visual C ++의 확장명은 비슷하지만 동일하지는 않습니다 __FUNCSIG__.

비표준 매크로의 경우 컴파일러 설명서를 참조하십시오. Visual C ++ 확장은 C ++ 컴파일러의 “사전 정의 된 매크로” 의 MSDN 설명서에 포함되어 있습니다. gcc 설명서 확장은 gcc 설명서 페이지 “함수 이름 문자열”에 설명되어 있습니다.


답변

원래 질문에 완전히 대답하지는 않았지만 이것은 아마도 대부분의 사람들이 인터넷 검색을 원했던 것일 것입니다.

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**)

답변

__PRETTY_FUNCTION__ C ++ 기능 처리 : 클래스, 네임 스페이스, 템플릿 및 오버로드

main.cpp

#include <iostream>

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

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

컴파일하고 실행하십시오.

g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out

산출:

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

함수 이름을 가진 스택 추적에 관심이있을 수도 있습니다. C 또는 C ++의 인쇄 호출 스택

우분투 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에 들어갔으므로 아직 다른 방법이 있습니다.

설명서는 다음과 같이 말합니다.

constexpr const char * function_name () const noexcept;

6 반환 :이 객체가 함수 본문의 위치를 ​​나타내는 경우 함수 이름에 해당하는 구현 정의 NTBS를 반환합니다. 그렇지 않으면 빈 문자열을 반환합니다.

여기서 NTBS는 “Null Terminated Byte String”을 의미합니다.

지원이 GCC에 도착하면 GCC 9.1.0에서 g++-9 -std=c++2a지원하지 않을 때 시도해 보겠습니다 .

https://en.cppreference.com/w/cpp/utility/source_location 클레임 사용법은 다음과 같습니다.

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

가능한 출력 :

info:main.cpp:16:main Hello world!

따라서 이것이 호출자 정보를 리턴하는 방법을 기록하므로 로깅에 사용하기에 적합합니다. 또한 C ++ 함수 내에 함수 이름을 가져 오는 방법이 있습니까?


답변

__func__섹션 8.4.1의 C ++ 0x 표준에 설명되어 있습니다. 이 경우 다음과 같은 형식의 사전 정의 된 함수 로컬 변수입니다.

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__. C __PRETTY_FUNCTION__와 동일 __func__하지만 C ++에는 형식 서명도 포함되어 있습니다.


답변

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

산출:

main ()에서 :
본관
본관
int __cdecl main (void)

A :: f ()에서 :
A <int, float> :: f
에프
void __cdecl A <int, float> :: f <bool> (void)

__PRETTY_FUNCTION__예상대로 트리거 선언되지 않은 식별자 오류를 사용 합니다.