2014-04-25 6 views
5

this question에 대한 샘플 코드를 조사 할 때 이후에 std::cout을 사용하지 못하게하는 것이 정의되지 않은 동작이라고 생각했습니다. 그러나 그것이 작동하지 않는 실제 원인 인 attempting to print a null pointer caused std::ios_base::badbit and std::ios_base::failbit to be set in its stream state으로 밝혀졌습니다. 이 때문에 실제로는 이면 궁금합니다. 정의되지 않음 null 포인터를 인쇄하려는 (시도한) 동작입니다. 그래서 내 질문은 다음과 같습니다.null 포인터를 인쇄하고 있습니까? 정의되지 않은 동작입니까?

  1. null 포인터를 인쇄하는 것은 정의 된 동작입니까? 그렇다면 스트림 삽입기에 대한 원인은 무엇입니까? 나는 삽입자가 널 포인터를 역 참조하지 않을만큼 똑똑하다는 것을 확신한다.

  2. 삽입 포인터가이 컨텍스트에서 널 포인터 (특히 badbit)를 만나면 오류 마스크를 설정하는 이유를 알고 싶습니다. 문자열 리터럴의 종료와 같이 처리하지 않는 이유는 무엇입니까?

표준이 없기 때문에 불행히도 하나의 소스 만 발견되어 불행하게도 연결이 끊어졌습니다.

+1

libstdC++는 필요하지 않을 때 여분의'nullptr' 검사를하고있을 수도 있습니다. clang + libC++로 빌드 할 때 [seg faults] (http://coliru.stacked-crooked.com/a/2078b21d2ce9050d) 프로그램. clang + libstdC++ – Praetorian

+2

"나는 삽입자가 null 포인터를 역 참조하지 않을만큼 똑똑하다고 확신합니다." - 일반적으로 C++ 표준은 컴파일러가 수행해야하는 작업과 다른 작업을 수행 할 필요가 없다고 말합니다. 'operator << (char *)'에 대한 모든 호출 전에 여분의 NULL 검사를 수행하도록 올바르게 코딩 된 프로그램의 속도를 줄입니다. –

+0

@MattMcNabb : lol C++ 입출력 스트림처럼 무서운 속도로 작업 할 때 null 체크의 속도가 걱정 스럽다고 생각하지 않습니다. – Mehrdad

답변

11

basic_ostream의 기능은 char*이 null이 아니며 포인터가 가리키는 문자열을 인쇄하도록 설계되었습니다. 따라서 char*cout으로 보내는 것은 정의되지 않은 동작입니다. (C++ 11 27.7.3.6.4/3 "문자 삽입 자 함수 템플리트"참조).

그러나 basic_ostreamoperator<<(basic_ostream<>&, const void*) 함수는 단순히 포인터의 값을 출력하므로 null 포인터가 해당 오버로드와 함께 제대로 작동합니다.

+5

'27.7을하는 대신'[ostream.inserters.character]'를 통해 표준을 인용하면. 3.6.4'라면 챕터 나 섹션 번호를 다시 매기는 다른 버전에서 여전히 유효한 참조 일 가능성이 더 큽니다. –

2

GCC ostream.tcc 라인 319 :

template<typename _CharT, typename _Traits> 
    basic_ostream<_CharT, _Traits>& 
    operator<<(basic_ostream<_CharT, _Traits>& __out, const char* __s) 
    { 
    if (!__s) 
__out.setstate(ios_base::badbit); 

GCC는 단순히 어쨌든 정의되지 않은 때문에 괜찮 표준이 보장하지 않는 검사를 수행하고 있습니다.