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.
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.
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.
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
Tags und Links c++ expression unsigned built-in-types