was passiert, wenn ich signierte und vorzeichenlose Typen mische?

8

Ich studiere die C ++ - Sprache und habe Zweifel an der Typkonvertierung. Könnten Sie mir erklären, was in einem solchen Ausdruck passiert:

%Vor%

Hier weiß ich, dass das Ergebnis 52 sein wird, wenn ich die Regeln anwende, wenn wir zwei mathematische Operatoren haben. Aber ich frage mich, was passiert, wenn der Compiler, um einen vorzeichenlosen Wert zu konvertieren, einen temporären Typ ohne Vorzeichen erzeugt? Der Ausdruck sollte jetzt 10 -4494967254 sein.

    
Piero Borrelli 01.09.2014, 15:32
quelle

3 Antworten

9

Vereinfacht ausgedrückt: Wenn Sie Typen des gleichen Rangs mischen (in der Reihenfolge int , long int , long long int ), gewinnt der unsignierte Typ "gewinnt" und die Berechnungen werden in diesem unsignierten Typ ausgeführt. Das Ergebnis hat denselben vorzeichenlosen Typ.

Wenn Sie Typen unterschiedlichen Rangs mischen, gewinnt der höherrangige Typ "gewinnt", wenn er alle Werte des niedrigeren Rangs darstellen kann. Die Berechnungen werden innerhalb dieses Typs durchgeführt. Das Ergebnis ist von diesem Typ.

Wenn schließlich der Typ mit dem höheren Rang nicht alle Werte des Typs mit dem niedrigeren Rang darstellen kann, wird die vorzeichenlose Version des Typs mit dem höheren Rang verwendet. Das Ergebnis ist von diesem Typ.

In Ihrem Fall haben Sie Typen mit demselben Rang ( int und unsigned int ) gemischt, was bedeutet, dass der gesamte Ausdruck innerhalb von unsigned int type ausgewertet wird. Der Ausdruck, wie Sie richtig sagten, ist jetzt 10 - 4294967254 (für 32 Bit int ). Vorzeichenlose Typen folgen den Regeln der Modulo-Arithmetik mit 2^32 ( 4294967296 ) als Modulo. Wenn Sie das Ergebnis sorgfältig berechnen (was arithmetisch als 10 - 4294967254 + 4294967296 ausgedrückt werden kann), wird es als das erwartete 52 ergeben.

    
AnT 01.09.2014, 16:15
quelle
2

1) Aufgrund der Standard-Regeln für Werbeaktionen wird signed type a vor der Subtraktion in den Typ unsigned hochgestuft. Diese Aktion erfolgt nach dieser Regel (C ++ Standard 4.7 / 2):

  

Wenn der Zieltyp unsigniert ist, ist der resultierende Wert am wenigsten   Ganzzahl ohne Vorzeichen, kongruent zur Quell - Ganzzahl (Modulo 2n, wobei n ist   die Anzahl der Bits, die zur Darstellung des Typs ohne Vorzeichen verwendet werden.)

Algebraisch a wird eine sehr große positive Zahl und sicherlich größer als u .

2) u - a ist ein anonymer temporärer Typ und ein unsignierter -Typ. (Sie können dies überprüfen, indem Sie auto t = u - a schreiben und den Typ von t in Ihrem Debugger überprüfen.) Mathematisch wird dies eine negative Zahl sein, aber bei einer impliziten Konvertierung in den unsignierten Typ wird eine ähnliche Wraparound-Regel wie oben aufgerufen. p>

Kurz gesagt, die beiden Konvertierungsoperationen haben gleiche und entgegengesetzte Effekte und das Ergebnis wird 52 sein. In der Praxis könnte der Compiler all diese Konvertierungen optimieren.

    
Bathsheba 01.09.2014 15:47
quelle
-1

hier ist der disassemble Code sagt:

Er setzt -42 zuerst auf sein Komplement und führt die Unteroperation aus. Das Ergebnis ist 10 + 42      0x0000000000400835 <+8>: movl %code%xa,-0xc(%rbp) 0x000000000040083c <+15>: movl %code%xffffffd6,-0x8(%rbp) 0x0000000000400843 <+22>: mov -0x8(%rbp),%eax 0x0000000000400846 <+25>: mov -0xc(%rbp),%edx 0x0000000000400849 <+28>: sub %eax,%edx 0x000000000040084b <+30>: mov %edx,%eax

    
Jinghui.You 01.09.2014 16:06
quelle