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


답변:


266

__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 설명서 페이지 "함수 이름 문자열"에 설명되어 있습니다.


C99 사양 (소스에 플로팅 링크가 있음)에 연결할 수 있습니까?
Matt Joiner

1
@ legends2k : 아니요, C ++ 11의 "구현 정의 문자열"입니다. 그것은 사양의 실제 언어입니다. §8.4.1 [dcl.fct.def.general] / 8을 참조하십시오.
James McNellis

2
gcc와 VC는 모두를 제공 __FUNCTION__하지만 약간 다른 작업을 수행합니다. gcc는에 해당 __func__합니다. VC는 장식되지는 않았지만 여전히 꾸며진 버전의 이름을 제공합니다. "foo"라는 메소드의 경우 gcc가 "foo"VC를 제공 "my_namespace::my_class::foo"합니다.
Adrian McCarthy

1
궁금한 점은 MSVC 2017 CE를 사용하고 있으며 입력 __PRETTY_FUNCTION__할 때 목록에 사용 가능한 것으로 표시되고 마우스를 움직일 때 함수 이름에 대한 정보를 표시하지만 컴파일하지는 않습니다.
프랜시스 커 글러

1
@FrancisCugler 나도 이것에 놀랐습니다! 그것은 내 질문을 참조 stackoverflow.com/questions/48857887/...
아담 바두라

108

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

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

6
나는이 적절한 대답하지 알고 있지만, (그들은 스스로를 시도 할 게으른 경우)는 :)이 구글 거의 모든 사람들이보고 싶어 무엇을 아마
페트르

5
공정한 전화, 이것은 반갑습니다.
Matt Joiner

13
clang 3.5의 동일한 출력
Doncho Gunchev

좋아,하지만 __func__다른 기능에 포함되어 있으면 작동합니까? function1이 있다고 가정하면 인수가 필요하지 않습니다. function1은를 포함하는 function2를 호출하며 __func__, 어떤 함수 이름이 인쇄됩니까, 1 또는 2?
MarcusJ

@MarcusJ 스스로 시도해 보지 않겠습니까 ... __func__매크로는 현재 사용중인 모든 함수로 변환됩니다. f1에 넣고 f2에서 f1을 호출하면 항상 f1을 얻게됩니다.
Petr

41

__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 ++ 함수 내에 함수 이름을 가져 오는 방법이 있습니까?


13

__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 ++에는 형식 서명도 포함되어 있습니다.


__func__C ++ 03의 일부가 아닙니다. C ++ 0x에 추가되었지만 C ++ 0x는 아직 "C ++ 표준"이 아니며 아직 초안 형식입니다.
James McNellis

2
@JamesMcNellis 소음을 제거하는 것은 이제 코멘트를 명확하게한다
daramarak

7

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__예상대로 트리거 선언되지 않은 식별자 오류를 사용 합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.