2013-07-06 15 views
9

czy false może być pośrednio przekształca się wskaźnik jest różny od szczęk ++ i G ++fałszywe domyślnie przejść na NULL

g ++ - 4,8: ​​zawsze ostrzeżenie lub bez -std = C++ 11

clang ++ (trunk): ostrzeżenie, jeśli bez parametru -std = C++ 11, i błąd, jeśli z -std = C++ 11

Więc każdy wie, dlaczego g ++ i clang ++ zachowuje się inaczej i kto ma rację? Jakie akapity w standardzie C++ (zarówno C++ 03, jak i C++ 11) mówią o sytuacji.

Dzięki.

[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

Co robi 'clang ++ -std = C++ 03'? – zch

+0

Ostrzeżenie, tak samo jak bez -std = C++ 11 –

+0

Zastanawiam się, czy to nie wszystko pochodzi z C z C++. C++ 03 jest kompatybilny z C89, w którym nie było typu bool, a "false" i "true" byłyby tylko makrami; jednak C++ 11 jest kompatybilny z C11, który ma typ bool i dlatego nie ma już sensu uznawać 'false' za kolejny alias typu "0". –

Odpowiedz

6

Powiedziałbym dzyń z C++ 11 ma rację:

3.9.1 Podstawowe typy [basic.fundamental]

6 Wartości typu bool są albo true lub false. [Uwaga: nie ma podpisanych, niepodpisanych, krótkich ani długich typów lub wartości bool. - end note] Wartości typu bool uczestniczą w integralnych promocjach (4.5).

bool nie ma wartość zero, to nie może być przekształcony w NULL:

4.10 wskaźnika konwersji [conv.ptr] jest integralną

1 null stały wskaźnik stała ekspresja (5.19) wartość całkowita typu , która ocenia zero do lub wartość typ std :: nullptr_t. Stała wskaźnika zerowego może zostać przekonwertowana na typ wskaźnika ;

Jeden może sugerować sekwencję konwersji składający integralnej promocji (bool do int) i zerowej konwersji wskaźnik, ale to nie jest ważne:

4 standardowe konwersje [conv]

1 Standardowe konwersje to niejawne konwersje z wbudowanym znaczeniem. Klauzula 4 wylicza pełny zestaw takich konwersji. Standardowa kolejność konwersji sekwencji standardowych konwersji w następującej kolejności:

  • zero lub jeden konwersji z następującego zbioru: lwartość do RValue konwersji tablica-to-wskaźnika konwersji i funkcji do -pointer konwersja.
  • zero lub jeden konwersja z następującego zestawu: integralne promocje, zmiennoprzecinkowe promocja, integralne konwersje, pływające punkt konwersji zmiennoprzecinkowej integralne konwersje wskaźnik konwersje, wskaźnik konwersji członkowskich oraz logiczne konwersje .
  • Zero lub jedna konwersja kwalifikacyjna.

[Uwaga: standardowa sekwencja konwersji może być pusta, tzn. Może zawierać bez konwersji. - nota końcowa] Standardowa sekwencja konwersji zostanie zastosowana do wyrażenia, jeśli będzie to konieczne, aby przekonwertować go na wymagany typ docelowy .

+1

Oba kompilatory pozwalają na to w trybie C++ 03, więc Clang jest tak samo zły jak GCC (zauważ, już to zgłosiłem, zobacz http://www.open-std.org/jtc1/sc22/wg21/docs /cwg_closed.html#1448). W C++ 11, clang pozwala na to tylko z powodu prawdopodobnej (?) Nadchodzącej zmiany w późniejszym standardzie, która będzie blokować stałe całkowe stałe wyrażenie z zerowych stałych wskaźnikowych, z wyjątkiem zwykłego "0". Niestety, bliski powód "Rozwiązanie problemu 903 wyjaśnia, że ​​false nie jest zerową stałą wskaźnika". jest całkowicie nieistotny w moim raporcie o problemie :( –

+0

Cóż, nie jest całkowicie nieistotny, ale brakuje mu tego samego problemu z 'bool v = true; int a = {v};' - to z definicji jest "zwężający się" i źle powstały, ale implementacje mają tendencję do akceptowania go.Nie byłoby lepiej wyjaśnić definicję "fałszywego" i "prawdziwego", aby powiedzieć, co jest tutaj zamierzone. –

Powiązane problemy