Compilerwarnung (Stufe 2) C4146
unärer Minusoperator, der auf nicht signierten Typ angewendet wurde, ergebnis noch nicht signiert
Nicht signierte Typen können nur nicht negative Werte enthalten, sodass unäre Minuswerte (Negation) normalerweise nicht sinnvoll sind, wenn sie auf einen nicht signierten Typ angewendet werden. Sowohl der Operand als auch das Ergebnis sind nicht negativ.
Hinweise
Wenn Sie ein negatives ganzzahliges Literal ausdrücken, wird der -
vor dem Wert als unärer Negationsoperator analysiert. Der Compiler wendet den Operator an, nachdem er den numerischen Wert analysiert hat. Wenn der numerische Wert in den Bereich eines nicht signierten ganzzahligen Typs passt, aber nicht den entsprechenden ganzzahligen Typ, interpretiert der Compiler den Wert als nicht signiert. Ein nicht signierter Wert ist vom Unary Negation-Operator unverändert.
Diese Warnung tritt häufig auf, wenn Sie versuchen, den Minimalwert int
-2147483648 oder den Minimalwert long long
-9223372036854775808 auszudrücken. Diese Werte können nicht als -2147483648 oder -922337203685475808ll geschrieben werden. Der Grund dafür ist, dass der Compiler den Ausdruck in zwei Phasen verarbeitet: Zuerst analysiert er den numerischen Wert und wendet dann den Negationsoperator an. Wenn der Compiler beispielsweise -2147483648 analysiert, führt er die folgenden Schritte aus:
Die 2147483648 wird ausgewertet. Da es größer als der Maximalwert
int
von 2147483647 ist, aber dennoch in einenunsigned int
passt, istunsigned int
der Typ der 2147483648 .Unär minus wird auf den nicht signierten Wert mit einem nicht signierten Ergebnis angewendet, das auch 2147483648 wird.
Der nicht signierte Typ des Ergebnisses kann zu unerwartetem Verhalten führen. Wenn das Ergebnis in einem Vergleich verwendet wird, kann beispielsweise ein nicht signierter Vergleich verwendet werden, wenn der andere Operand ein int
.
Sie können C4146 vermeiden, indem Sie C4146 oder das <limits.h>
C++-Äquivalent verwendenINT_MIN
. <climits>
LLONG_MIN
Diese Werte haben signierte Typen.
Die /sdl
Compileroption (Zusätzliche Sicherheitsüberprüfungen aktivieren) erhöht diese Warnung auf einen Fehler.
Beispiel
Im folgenden Beispiel wird das unerwartete Verhalten veranschaulicht, das auftreten kann, wenn der Compiler eine Warnung C4146 generiert:
// C4146.cpp
// compile with: /W2
#include <iostream>
void check(int i)
{
if (i > -9223372036854775808ll) // C4146
std::cout << i << " is greater than the most negative long long int.\n";
}
int main()
{
check(-100);
check(1);
}
In diesem Beispiel betrachtet der Compiler -9223372036854775808ll nicht signiert, obwohl das Literal über ein ll
Suffix verfügt und der Negationsoperator angewendet wird. Um den <
Vergleich vorzunehmen, wird vom Compiler im Hintergrund signiert auf unsigned long long int
i
. Die erwartete zweite Zeile , 1 is greater than the most negative long long int
wird nicht gedruckt, weil ((unsigned long long int)1) > 9223372036854775808ull
"false" ist.
Um das Beispiel zu beheben, schließen <climits>
Sie -9223372036854775808ll in LLONG_MIN
ein.