typecasting zu unsigned in C
int a = -534;
unsigned int b = (unsigned int)a;
printf("%d, %d", a, b);
Drucke -534, -534
Warum ist die Umwandlung nicht stattfindet?
Ich erwartet, dass es -534, 534
Wenn ich den code ändern, um
int a = -534;
unsigned int b = (unsigned int)a;
if(a < b)
printf("%d, %d", a, b);
seine nicht drucken nichts... nach all a
ist weniger als b
??
- Sie möchten möglicherweise überprüfen Sie Ihre compiler docs und sehen, ob es eine option zum überprüfen printf-format-Bezeichner. gcc -Wformat, die hätten gewarnt, Sie über die %d vs. %u, was zur compile-Zeit.
- stackoverflow.com/questions/50605/...
- Dies sollte nicht über einen C++ - tag.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Erste, Sie brauchen nicht die Darsteller: der Wert von
a
implizit inunsigned int
mit der Zuordnung zub
. Also deine Aussage ist äquivalent zu:Nun eine wichtige Eigenschaft von
unsigned
integralen Typen in C und C++ ist, dass Ihre Werte stets im Bereich [0, max], wo max fürunsigned int
istUINT_MAX
(definiert inlimits.h
). Wenn Sie einen Wert zuweisen, der nicht in diesem Bereich, es wird in diesem Bereich. Also, wenn der Wert negativ ist, fügen SieUINT_MAX+1
wiederholt, um es in den Bereich [0,UINT_MAX
]. Für den code oben, es ist, als ob wir geschrieben:unsigned int b = (UINT_MAX + a) + 1
. Dies ist nicht gleich zu-a
(534).Beachten Sie, dass die oben wahr ist, ob das zugrunde liegende Darstellung im Zweierkomplement, diejenigen, die' Ergänzung, oder sign-magnitude (oder irgendeine andere exotische Codierung). Man kann sehen, dass mit so etwas wie:
Auf einer typischen zwei-Komplement-Maschine mit einem 4-byte -
int
,c
ist0xff
, undu
ist0xffffffff
. Der compiler hat dafür zu sorgen, dass, wenn der Wert-1
zugeordnet istu
es konvertiert einen Wert in Höhe vonUINT_MAX
.Nun gehen wir zurück zu Ihrem code, der
printf
format-string ist falsch, fürb
. Sollten Sie verwenden%u
. Wenn Sie das tun, werden Sie feststellen, dass es druckt den Wert vonUINT_MAX - 534 + 1
statt534
.Beim Einsatz in der Vergleichsoperator
<
, dab
istunsigned int
,a
ist auch konvertiertunsigned int
. Dies, da mitb = a
; früher, bedeutet, dassa < b
falsch ist:a
alsunsigned int
gleichb
.Lassen Sie uns sagen, Sie haben einen eigenen ergänzen Maschine, und Sie tun:
Lassen Sie uns sagen, ein
char
(signed oder unsigned) ist 8-bit auf der Maschine. Dannc
unduc
speichert folgende Werte ein bit-Muster:Beachten Sie, dass die bit-Muster der
c
unduc
sind nicht das gleiche. Der compiler muss sicherstellen, dassc
hat den Wert-1
, unduc
hat den WertUCHAR_MAX
, die 255 auf dieser Maschine.Gibt es mehr details auf meine Antwort auf eine Frage hier auf SO.
Weil Sie
%d
für den Druck. Verwenden%u
für unsigned. Da printf ist ein vararg-Funktion, kann es nicht wissen, die Typen der Parameter und muss stattdessen auf die Formatbezeichner. Weil dies die Art Darsteller, die Sie tun, hat keine Auswirkungen.reinterpret_cast
-ed zurück vonprintf()
wegen%d
.%d
bedeutet: "nimm den Wert und interpretieren es als signed int"if
scheitern? Bitte sehen Sie die bearbeitete ques.unsigned int
Wert nicht negieren (änderung -534 bis 534), wandelt es um die kleinste positive Zahl, die kongruent zu der ursprünglichen moduloUINT_MAX + 1
. Wenn Sie 32-bit -unsigned int
s, -534 konvertieren 4294966762 (auf 2s ergänzen Maschine, dieser hat die gleichen bitweise Darstellung als -534).reinterpret_cast
-ed.printf()
ist eine C-Funktion. Sie sind nur gegossen.reinterpret_cast
, ich meinte nur die Semantik: die binäre Darstellung wird interpretiert als int ohne jede Rücksicht wurde der Typ des Arguments. In C++ (was wir alle sind vertraut mit) diese Semantik wird ausgedrückt durchreinterpret_cast
, in der Erwägung, dass in C der cast ist eine Mischung unterschiedlicher Semantik (zumindest aus C++ - Sicht).Ihre Bezeichner in der printf-fragt printf drucken eine Ganzzahl, also die zugrunde liegende bytes interpretiert werden als eine vorzeichenbehaftete Ganzzahl.
Sollten Sie angeben, dass Sie möchten, eine vorzeichenlose Ganzzahl, die durch die Verwendung
%u
.edit:
a==b
gilt für den Vergleich, das ist seltsam Verhalten, aber es ist durchaus gültig. Sie haben sich nicht verändert, die zugrunde liegenden bits haben Sie nur gebeten, den compiler zu behandeln, die zugrunde liegenden bits in einer bestimmten Art und Weise. Daher ein bitweiser Vergleich ergibt true.[speculation]
Würde ich vermuten, dass das Verhalten kann variieren zwischen compiler-Implementierungen, d.h., eine fiktive CPU möglicherweise nicht die gleiche Logik für beide signiert und unsigniert Ziffern, in dem Fall ein bitweiser Vergleich ausfallen würde.[/speculation]
if
scheitern? Bitte sehen Sie die bearbeitete Frage.a
undb
verschiedene bits,a == b
wahr ist. Siehe meine Antwort für details.C kann ein hässliches Biest manchmal. Das problem ist, dass -534 stellt immer den Wert 0xfffffdea, ob es gespeichert ist, in eine variable mit dem Typ unsigned int oder signed int. Der Vergleich dieser Variablen müssen vom selben Typ, so wird man automatisch konvertiert, entweder in eine unsigned-oder signed int entsprechend die anderen. Einmal sind Sie vom gleichen Typ sind Sie gleich, wie Sie repräsentieren den gleichen Wert.
Scheint es wahrscheinlich, dass das Verhalten Sie wollen, ist durch die Funktion abs:
0xfffffdea
können variieren. E. g. auf 16-bit Maschinen, die es nur0xfdea
- und auf 64-bit Maschinen haben Sie 13-f ' s, gefolgt vondea
.dea
Teil ist nicht unbedingt richtig, auf einem Schild-Größe oder diejenigen, die' Ergänzung der Maschine.Ich denke, die ersten bei, warum b gedruckt wird, wie -534 wurde ausreichend beantwortet Tronic und Hassan. Sie sollten nicht über %d und sollte mit %u.
Soweit Ihre zweite Fall ist concered, wieder eine implizite typecasting geschehen wird und a und b wird dasselbe sein, wegen dem Ihr Vergleich ist Ausbeute das erwartete Ergebnis.
Soweit ich sehen kann, der wenn schlägt fehl, weil der compiler übernimmt die zweite variable betrachtet werden sollte, die denselben Typ wie der erste. Versuchen
wenn b > a)
um den Unterschied zu sehen.
Re 2. Frage:
Vergleich nie funktioniert, zwischen zwei verschiedenen Arten - Sie sind implizit immer ein cast auf den "kleinsten gemeinsamen Nenner", was in diesem Fall
unsigned int
. Böse und counter-intuitive, weiß ich.a==b
wahr ist.unsigned int
erlaubt ist in beiden Fällen (Fall #1, bei der Initialisierungb
und Fall #2 beim Vergleicha
undb
).Umwandlung eines integer-Typen von signed zu unsigned nicht ändern, die bit-Muster, es werden lediglich änderungen, die die interpretation der bit-Muster.
Haben Sie auch einen Formatbezeichner mismatch, %u sollte verwendet werden, für unsigned Integer, aber selbst dann ist das Ergebnis nicht 534 als Sie erwarten, aber 4294966762.
Wenn Sie möchten, stellen Sie einen negativen Wert positiv, einfach negieren:
Als für das zweite Beispiel-Operationen zwischen verschiedenen Typen mit unterschiedlichen Vorzeichen-ness beinhalten Arkane implizite Konvertierung Regeln - vermeiden. Stellen Sie Ihren compiler-warning-level hoch zu trap viele von diesen Fehlern. Ich schlage vor /W4 /WX in VC++ und -Wall-Werror -Wformat für den GCC zum Beispiel.