Wie Warning Wconversion-null vermeiden?
-
Hallo,
ich probiere gerade unser Projekt warnungsfrei zu kriegen (g++: Wall, clang++: Wall + Wsign-compare). Nur g++ feuert diese Warnung:
warning: passing NULL to non-pointer argument 1 of 'std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>]' [-Wconversion-null]Wir haben ein Test-Makro:
#define validateEquals(actualValue, validValue) if (!(actualValue == validValue)) { \ _errors++; \ _error = true; \ std::cerr << " equality test failed: " << actualValue << " instead of " << validValue << std::endl \ << " file: " << __FILE__ << " \t line: " << __LINE__ << std::endl \ << " statement: " << #actualValue << "==" << #validValue << std::endl; \ return;\ }Und das wird an der gewarnten Stelle so aufgerufen:
void* mesh = static_cast<void*> ( vertex.mesh() ); validateEquals ( mesh, NULL );Also wenn ich es richtig verstehe, ist das Problem, dass NULL==0 ist. Der Test könnte also falsch positiv sein,, wenn vertex.mesh() den Wert 0 anstelle des NULL Pointer zurückgibt.
Ich denke die Gefahr von falsch positiven Tests ist hier recht gering. Aber wie kann man das ganze so gestalten, dass die Warnung verschwindet?
nullptr ist leider keine Lösung, da wir uns z.Z. auf C++ 98 beschränken.
Viele Grüße!
-
Hallo.
Ich würde behaupten, dass es sich um einen Bug handelt. Die Warnung besagt, dass du
NULLals nicht-Zeiger verwendest (bei der formatierten Ausgabe an denstd::ostream!). Das kann nicht sein da einstd::ostream::operator<< (void const*)existieren müsste, wobei dann gar keine Konvertierung vonNULLin einenlong intvorgenommen werden sollte.
Siehe: http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltltEdit: Operator-Signatur korrigiert.
-
asfdlol schrieb:
Ich würde behaupten, dass es sich um einen Bug handelt.
Bug bei mir im Programm?
Die Warnung besagt, dass du
NULLals nicht-Zeiger verwendest (bei der formatierten Ausgabe an denstd::ostream!). Das kann nicht sein da einoperator<< (std::ostream&, void const*)existieren müsste, wobei dann gar keine Konvertierung vonNULLin einenlong intvorgenommen werden sollte.
Siehe: http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltltOk. Aber wie kann man das nun am besten Warnungsfrei hinkriegen? Die Ausgabe cout << NULL; scheint kein echtes Problem zu sein, es wird 0 ausgegeben.
-
Horus107 schrieb:
Ok. Aber wie kann man das nun am besten Warnungsfrei hinkriegen? Die Ausgabe cout << NULL; scheint kein echtes Problem zu sein, es wird 0 ausgegeben.
Ich weiss nicht was es bringt (vielleicht auch nichts), aber du könntest mal die Zeile in der du das Makro aufrufst ändern zu:
validateEquals ( mesh, static_cast<void*>(NULL) );Ich glaube jetzt im nachhinein, dass es nicht einmal garantiert ist, dass
NULLeher als Zeiger als alslongausgewertet wird.
-
Also, das funktioniert soweit, dass die Warnung weg ist. Allerdings ist immernoch 0==NULL, es gibt also einen Fall, wo der Test nicht fehlschlägt es aber sollte.
Aber ich denke, dass kann man mal als sehr theoretisch und recht unwahrscheinlich einstufen.Vielen Dank für Deine Hilfe!
-
Horus107 schrieb:
Allerdings ist immernoch 0==NULL,[...]
Und das ist auch gut so!
Horus107 schrieb:
Allerdings ist immernoch 0==NULL, es gibt also einen Fall, wo der Test nicht fehlschlägt es aber sollte.
Aber ich denke, dass kann man mal als sehr theoretisch und recht unwahrscheinlich einstufen.Ich kann dir leider nicht weiterhelfen solange ich nicht weiss, was
vertex::mesh()tut. Jedenfalls gibt es immer genau dann einen Fehler, wenn der Rückgabewert davon nicht 0 ist, das ist hoffentlich klar.
-
asfdlol schrieb:
Horus107 schrieb:
Allerdings ist immernoch 0==NULL,[...]
Und das ist auch gut so!
Es ist (ancheinend) C++ Standard, aber eigentlich ist für mich der NULL Pointer nicht gleich dem Zahlwert 0, so rein intuitiv.
Jedenfalls gibt es immer genau dann einen Fehler, wenn der Rückgabewert davon nicht 0 ist, das ist hoffentlich klar.
Und das ist auch gut so!
Ich will ja testen, ob die Funktion einen NULL Pointer zurückgibt.Aber soweit passt erstmal alles.
-
NULL ist 0 (oder 0ull) in C++. NULL ist nicht ((void*)0). Grund ist, dass NULL sowohl für Zeiger als auch für Memberfunktionszeiger funktionieren sollte, aber ((void*)0) nicht in einen Memberfunktionszeiger konvertierbar ist.
Falls du kannst, würde ich alle NULLs mit
nullptrersetzen, wobei du nullptr mitconst // It is a const object... class nullptr_t { public: template<class T> inline operator T*() const // convertible to any type of null non-member pointer... { return 0; } template<class C, class T> inline operator T C::*() const // or any type of null member pointer... { return 0; } private: void operator&() const; // Can't take address of nullptr } nullptr = {};auch in C++98 verwenden kannst. (Der Hack wäre
#define NULL nullptr, bessser aber von Hand ersetzen.)