
zurück
Ich war neugierig zu wissen, was passieren würde, wenn ich einer vorzeichenlosen Variablen einen negativen Wert zuweise.
Der Code wird in etwa so aussehen.
unsigned int nVal = 0;
nVal = -5;
Es gab mir keinen Compiler-Fehler. Als ich das Programm ausgeführt habe, wurde die nVal
wurde ein seltsamer Wert zugewiesen! Könnte es sein, dass einem 2er-Komplementwert zugewiesen wird nVal
?

Dennis Zickefoose
Für die offizielle Antwort – Abschnitt 4.7 conv.integral
„Wenn der Zieltyp vorzeichenlos ist, ist der resultierende Wert die kleinste vorzeichenlose Ganzzahl, die kongruent zur Quell-Ganzzahl ist (Modulo 2n wo n
ist die Anzahl der Bits, die verwendet werden, um den vorzeichenlosen Typ darzustellen). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —end note ]
Dies bedeutet im Wesentlichen, dass, wenn die zugrunde liegende Architektur in einer Methode speichert, die kein Zweierkomplement ist (wie Signed Magnitude oder One’s Complement), sich die Konvertierung in unsigned so verhalten muss, als wäre es ein Zweierkomplement.

Jasmeet
Es weist dem unsigned int das Bitmuster zu, das -5 (im Zweierkomplement) darstellt. Das wird ein großer vorzeichenloser Wert sein. Für 32-Bit-Ganzzahlen ist dies 2^32 – 5 oder 4294967291
Sie haben Recht, die Ganzzahl mit Vorzeichen wird im Zweierkomplement gespeichert, und die Ganzzahl ohne Vorzeichen wird in gespeichert vorzeichenlose binäre Darstellung. C (und C++) unterscheidet nicht zwischen den beiden, daher ist der Wert, den Sie erhalten, einfach der vorzeichenlose Binärwert der binären Darstellung des Zweierkomplements.
Es wird als positive Ganzzahl mit dem Wert der maximalen vorzeichenlosen Ganzzahl – 4 angezeigt (der Wert hängt von der Computerarchitektur und dem Compiler ab).
Übrigens
Sie können dies überprüfen, indem Sie ein einfaches C++-Programm vom Typ “Hallo Welt” schreiben und sich selbst davon überzeugen

Martin
Ja, du hast Recht. Der tatsächlich zugewiesene Wert ist so etwas wie alle gesetzten Bits außer dem dritten. -1 sind alle Bits gesetzt (hex: 0xFFFFFFFF), -2 sind alle Bits außer dem ersten und so weiter. Was Sie sehen würden, ist wahrscheinlich der Hex-Wert 0xFFFFFFFB, der dezimal 4294967291 entspricht.

Zafeer
Wenn Sie einer vorzeichenlosen Variablen einen negativen Wert zuweisen, verwendet sie die 2er-Komplementmethode, um sie zu verarbeiten, und bei dieser Methode werden alle 0s in 1s und alle 1s in 0s gespiegelt und dann 1 hinzugefügt. In Ihrem Fall haben Sie es mit int zu tun, das aus 4 Byte (32 Bit) besteht, sodass versucht wird, die 2er-Komplementmethode für eine 32-Bit-Zahl zu verwenden, wodurch das höhere Bit umgedreht wird. Zum Beispiel:
┌─[student@pc]─[~]
└──╼ $pcalc 0y00000000000000000000000000000101 # 5 in binary
5 0x5 0y101
┌─[student@pc]─[~]
└──╼ $pcalc 0y11111111111111111111111111111010 # flip all bits
4294967290 0xfffffffa 0y11111111111111111111111111111010
┌─[student@pc]─[~]
└──╼ $pcalc 0y11111111111111111111111111111010 + 1 # add 1 to that flipped binarry
4294967291 0xfffffffb 0y11111111111111111111111111111011
9928100cookie-checkWas passiert, wenn ich einer vorzeichenlosen Variablen einen negativen Wert zuweise?yes
Meine Vermutung (konnte es noch nicht im Standard finden) ist, dass das Verhalten technisch undefiniert ist. Außerdem vermute ich, dass Sie auf so ziemlich jedem Compiler sehen werden, was Sie erwarten. Obwohl Sie dieses Verhalten normalerweise sehen werden, ist es wahrscheinlich keine gute Idee, sich darauf zu verlassen.
– sblom
26. April 2010 um 6:50 Uhr
Es ist nicht undefiniert (vgl §4.7/2), aber die Darstellung (z. B. Zweierkomplement) wird vom Standard nicht vorgeschrieben.
– Georg Fritzsche
26. April 2010 um 6:52 Uhr
@gf (et al unten), cool. Sieht so aus, als ob das Verhalten tatsächlich explizit so definiert ist, wie Sie es erwartet haben, @viswanathan.
– sblom
26. April 2010 um 6:57 Uhr
Die zweite Zeile ist äquivalent zu
nVal = (unsigned int) -5;
. Die Besetzung von-5
zuunsigned int
ist definiert in 6.3.1.3. Die Darstellung im 2er-Komplement wird vom Standard nicht vorgeschrieben, aber der Algorithmus zum Konvertieren in vorzeichenlos lautet: “Der Wert wird konvertiert, indem wiederholt eins mehr als der maximale Wert, der im neuen Typ dargestellt werden kann, addiert oder subtrahiert wird, bis der Wert im Bereich liegt des neuen Typs.”– Pascal Cuoq
26. April 2010 um 6:59 Uhr
@Pascal: Sie scheinen sich auf C99 zu beziehen, aber die Frage ist mit C++ gekennzeichnet.
– Georg Fritzsche
26. April 2010 um 7:17 Uhr