2010-11-24 4 views
6

Ich habe diesen Beispielcode, der den folgende Warnung (VS2008-Compiler mit SP1) erzeugt:Compilerwarnung für unäre Operation auf unsigned int

Warnung C4146: unären minus Operator in unsigned Typ angewandt, das Ergebnis immer noch unsigned

Code:

void f(int n) 
{ 
} 

int main() 
{ 
    unsigned int n1 = 9; 
    f(-n1); 
} 

Aber seit Funktion f nimmt seinen Parameter als int sollte dieser Code nicht ohne Warnungen kompilieren?

Antwort

12

Norm 5.3.1/7

Der Operand des unären - Operator werden müssen arithmetische oder Aufzählung Art und das Ergebnis ist die Negation der seiner Operanden. Integralpromotion ist durchgeführt an Integral oder Enumeration Operanden. Das Negativ einer vorzeichenlosen Menge wird berechnet, indem sein Wert von 2n subtrahiert wird, wobei n die Anzahl von Bits im umgestuften Operanden ist. Der Typ des Ergebnisses ist der Typ des beworbenen Operanden.

Und der Absatz über Integral Promotion 4.5/1

rvalue vom Typ char, signed char, unsigned char, short int oder unsigned short int kann einem rvalue des Typs int umgewandelt werden, wenn int alle Werte von der darstellen kann Quelle Art; Andernfalls kann der Quell-R-Wert in einen R-Wert vom Typ unsigned int konvertiert werden.

d. H. Ein unsigned int wird nicht zu einem int hochgestuft.

15

wenn x vom Typ unsigned int, dann ist so -x und es ist praktisch äquivalent zu 2n-x (wobei n meist wahrscheinlich 32). Um zu vermeiden, um die Warnung und richtiges Verhalten zu erhalten, zu gieße int:

f(-static_cast<int>(n)); 

ich empfehlen würde, die „Ausdrücke“ Kapitel des Standard-C++ zu lesen. Dort werden Sie sehen, dass in dem Ausdruck -x integrale Promotions stattfinden auf x, was bedeutet, dass fast alles auf int befördert wird, aber unsigned int ist nicht.

Schauen Sie sich das sehr interessantes Beispiel:

template<class T> 
void f(T x) 
{ 
    //somehow print type info about x, e.g. cout << typeid(x).name() or something 
} 

int main() 
{ 
    char x; 
    f(x); 
    f(+x); 
    f(-x); 
} 

druckt:

char 
int 
int 

Aber char ->int ist integraler Förderung, während unsigned int ->int eine Umwandlung

ist
+0

Siehe @ Andreas Antwort für Zitat und Definition der Förderung :) –

+0

Das funktioniert mit dem Wert "9", aber ich denke im Allgemeinen '(int) (- (vorzeichenlose) x)' und '- (int) x' sind nicht genau gleich, denn wenn x INT_MIN ist, ist das Anwenden von Minus auf einen nicht definierten Überlauf, während das unäre Minus auf einem vorzeichenlosen Wert für alle vorzeichenlosen Werte gut definiert ist. Korrigiere mich, wenn ich falsch liege. –

2

Die Parameter ist Wert übergeben. Im Funktionsaufruf f (-n1) wird der Operator angewendet, bevor der Parameter an die Funktion übergeben wird. Daher die Warnung.

0

Der Compiler warnt Sie, dass die Anwendung von unary minus auf einen unsigned int ist eine ungewöhnliche Sache zu tun und möglicherweise nicht das Ergebnis, das Sie erwarten. Das Ergebnis, das Sie in diesem Fall erhalten, entspricht dem Aufruf von f (4294967287u), wenn Sie einen 32-Bit-Compiler verwenden.