2013-08-03 3 views
5

프로그래밍 수수께끼, 재미 :C++ 함수 포인터 다음 코드를 감안할 때

#include <string> 
#include <iostream> 

int main() 
{ 
    std::string prefix("->"), middle(), suffix("<-"); 
    std::cout << "Test: " << prefix << middle << suffix << std::endl; 

    return 0; 
} 

고급 C++ 프로그래머가 즉시 middle()std::string의 기본의 ctor를 호출하지 않는 것을 볼 수 있습니다 대신 함수 선언입니다.

하지만 흥미로운 기능 : 비주얼 스튜디오의 링커 오류 달리

Test: ->1<- 

: 왜 GCC는 다음과 같은 출력을 생성합니까? 아무도 여기서 무슨 일이 일어나는 지 알아?

+0

나는 downvote와이 질문에 대한 가까운 요청을 받고있다. 그런 질문은 정말 주제에 맞지 않습니까? –

답변

7

cout과 함께 사용할 경우 함수 포인터가 bool으로 변환됩니다.

함수 포인터가 암시 적으로 void *으로 변환되지 않는 이유는 무엇입니까? < <은 과부하가되는 이유는 무엇입니까? 왜냐하면 함수 포인터는 객체 포인터가 아니기 때문입니다.

C++ 11 §4.10/2

T는, CV 무효 포인터 '유형의 prvalue로 변환 할 수있는 개체 유형 인 "CV T, 포인터'유형의 prvalue ". "cv T에 대한 포인터"를 "cv void에 대한 포인터"로 변환 한 결과는 마치 객체가 T 유형의 가장 많이 파생 된 객체 (1.8) 인 것처럼 T 유형의 객체가 상주하는 저장 위치의 시작을 가리 킵니다 (즉, 기본 클래스 하위 객체가 아닙니다). 널 포인터 값은 목적지 유형의 널 포인터 값으로 변환됩니다.

+2

감사합니다. 나는 그런 것을 추측하고있었습니다. 왜 VS가 링커 오류를 생성하는지 우연히 알고 있습니까? 어떤 행동이 "표준"이고 어느 행동이 "잘못"입니까? –

+4

@ D.R : 프로그램에 정의되지 않은 동작이 있다고 생각합니다. 둘 다 "정확합니다". 규칙은 다음과 같습니다. "모든 프로그램은 해당 프로그램에서 odr- 사용되는 모든 비 인라인 함수 또는 변수에 대해 정확히 하나의 정의를 포함해야하며 ** 진단 필요 없음 **." –

+0

이 항목은 무엇인가요? http://stackoverflow.com/questions/2064692/how-to-print-function-pointers-with-cout –

1

Yu가 말한 것처럼 함수 포인터는 bool으로 변환됩니다.

g ++ 최적화 프로그램은 분명히 변환을 사전 평가하는 반면 Visual C++은 실제로 함수 주소가 null인지 여부를 테스트하는 코드를 생성하며 링커가 함수 주소를 제공해야합니다.

규칙은

프로그램마다 그 프로그램의 ODR으로 사용되는 모든 비 인라인 함수 또는 변수의 정확히 하나의 정의를 포함하여야한다는 것이다; 진단 필요 없음.

해당 주소를 사용하고 있기 때문에 odr-used입니다. 정의를 제공하지 않으면이 규칙을 위반하게되며 Standard는 진단을 요구하지 않습니다. 즉, 툴체인은 원하는 모든 작업을 자유롭게 수행 할 수 있습니다.

Visual C++에서 진단을 생성하고 있지만 필수는 아닙니다.

g ++는 함수 포인터에 대한 실제 함수의 감소가 결코 null 함수 포인터를 생성 할 수 없다는 것을 알고 있기 때문에 bool으로 실제 변환 결과를 제공합니다.

그러나 표준에서 툴체인이 여기에서 할 수 있거나 할 수없는 것을 말하지 않기 때문에 하드 드라이브를 포맷해도 똑같이 유효합니다.

관련 문제