2013-07-06 4 views
9
여부 false는 암시 적으로 포인터로 변환 할 수 사이에 차이가있다

그 소리 ++와 g ++ :거짓 암시 적으로 포인터를 null로 변환

그램 ++ - 4.8 : 또는 -std = C++ 11

없이 항상 경고

clang ++ (트렁크) : -std = C++ 11이 아닌 경우 경고, -std = C++ 인 경우 오류 11

g ++ 및 clang ++의 작동 방식이 다른 이유는 무엇입니까? C++ 표준 (C++ 03과 C++ 11 모두)에서 어떤 단락이 상황에 대해 이야기합니다.

감사합니다. C++ 11

[hidden ~]$ cat b.cpp 
const char* f() { return false; } 

[hidden ~]$ g++ -c b.cpp 
b.cpp: In function ‘const char* f()’: 
b.cpp:1:26: warning: converting ‘false’ to pointer type ‘const char*’ [-Wconversion-null] 
const char* f() { return false; } 
         ^
[hidden ~]$ g++ -std=c++11 -c b.cpp 
b.cpp: In function ‘const char* f()’: 
b.cpp:1:26: warning: converting ‘false’ to pointer type ‘const char*’ [-Wconversion-null] 
const char* f() { return false; } 
         ^
[hidden ~]$ clang++ -c b.cpp 
b.cpp:1:26: warning: initialization of pointer of type 'const char *' to null from a constant boolean expression [-Wbool-conversion] 
const char* f() { return false; } 
         ^~~~~ 
1 warning generated. 
[hidden ~]$ clang++ -std=c++11 -c b.cpp 
b.cpp:1:26: error: cannot initialize return object of type 'const char *' with an rvalue of type 'bool' 
const char* f() { return false; } 
         ^~~~~ 
1 error generated. 
+0

'clang ++ -std = C++ 03'은 무엇을합니까? – zch

+0

경고, -std = C++이없는 경우와 동일 11 –

+0

이 모든 것이 C++의 C 루 트를 따르지 않는지 궁금합니다. C++ 03은 bool 타입이없고'false'가 있고'true' 매크로 만 매크로가 될 수있는 C89와 호환됩니다. 그러나 C++ 11은 bool 타입을 가진 C11과 호환 가능하므로 더 이상 'false'를'0'의 또 다른 별칭으로 간주하지 않습니다. –

답변

6

I 말하는 것 연타 오른쪽이다

3.9.1 기본적인 유형 [basic.fundamental] bool 형식의

6 개의 값 중 하나 이다 true 또는 false. [주의 : 서명 된, 부호없는, 짧거나 긴 bool 타입이나 값은 없습니다. - end 주] bool 유형의 값은 통합 프로모션 (4.5)에 참여합니다.

bool는 제로 값을 갖고 있지 않기 때문에, 포인터가 null로 변환 될 수

4.10 포인터 전환 [conv.ptr]

1 A 널 포인터 상수는 일체 정수식 의 상수 표현 (5.19) prvalue는 0으로 계산됩니다. 또는 유형 std :: nullptr_t의 prvalue입니다. null 포인터 상수는 포인터 유형으로 변환 될 수 있습니다.

하나는 통합 추진 (intbool)와 널 포인터 변환 구성된 변환 순서를 제안 할 수도 있지만이 유효하지 않을 :

4 표준 변환 [전환]

1 표준 변환은 내장 된 의미를 가진 암시 적 변환입니다. 4 절에서는 그러한 변환의 전체 집합을 나열합니다.

  • 제로 또는 다음 세트에서 하나의 전환 : 좌변 투 r- 수치 변환 어레이 간 포인터 변환 한 함수에 표준 변환 시퀀스는 순서 다음 표준 전환 시퀀스 인 -pointer 변환.다음 세트에서
  • 0 또는 1 변환 : 통합 프로모션, 부동 소수점 추진, 통합 변환, 부동 통합 변환을, 점 변환을 떠, 포인터 변환, 회원 변환에 대한 포인터 및 부울 변환 .
  • 0 또는 하나의 자릿수 변환.

[참고 : 표준 변환 시퀀스는 비어있을 수 있습니다. 즉, 은 전환으로 구성 될 수 없습니다. - end note] 표준 변환 시퀀스 은 필요한 경우 대상 유형 으로 변환해야하는 경우 표현식에 적용됩니다.

+1

두 컴파일러 모두 C++ 03 모드를 허용하므로 Clang은 GCC와 마찬가지로 잘못되었습니다 (참고로, 나는 오래 전에 이것을보고했습니다. http://www.open-std.org/jtc1/sc22/wg21/docs를 참고하십시오). /cwg_closed.html#1448). C++ 11에서 clang은 차후의 Standard에서 차후의 변경으로 인해 정수 상수 표현이 일반 "0"을 제외한 널 포인터 상수가되는 것을 금지하기 때문에 허용합니다. 불행히도 가까운 이유는 "문제 903의 해결책은 false가 널 포인터 상수가 아니라는 것을 분명히합니다." ( –

+0

) 글쎄, 완전히 관련이있는 것은 아니지만 같은 문제가 'bool v = true; int a = {v};'-이 정의가 "좁혀지고" 구현은 그것을 받아들이는 경향이있다. 여기서 의도하는 바를 말하기 위해 "거짓"과 "사실"의 정의를 명확하게하는 것이 낫다. –

관련 문제