printf fügt zusätzliches `FFFFFF` zum Hex-Print aus einem char-Array hinzu [duplicate]
Lesezeit: 4 Minuten
Betrachten Sie den folgenden vereinfachten Code unten. Ich möchte einige binäre Daten/Streams aus einer Datei extrahieren und im Hexadezimalformat auf die Standardausgabe drucken.
Ich habe zusätzliche 3 Bytes 0xFFFFFF. Was ist los? Woher kommen die zusätzlichen Bytes?
Verwenden unsigned char Weil 0xAF > CHAR_MAX. Schmucklos char ist für Saiten.
– cremnr
27. Juni 2015 um 16:01 Uhr
@cremno es hängt tatsächlich vom System ab, einfach char kann signiert oder unsigniert sein.
– Ryan Haining
27. Juni 2015 um 16:04 Uhr
Standardwarnung: Nicht werfen void * (z. B. gegeben von malloc()) zu anderen Zeigern! Ebenfalls: sizeof(char) wird sich nie von unterscheiden 1denn das ist es, was der Standard nachgeben soll!
– zu ehrlich für diese Seite
27. Juni 2015 um 16:57 Uhr
Wenn das Ändern des Typs keine Option ist, werfen Sie ihn einfach: printf("%02X", (unsigned char)buf[i]);
– KrisWebDev
14. Juni 2016 um 18:46 Uhr
Warum gibt printf beim Drucken von hex nicht nur ein Byte aus?
– phuklv
4. November 2016 um 9:22 Uhr
Ryan Haining
Erweiterung anmelden. Ihr Compiler implementiert char Als ein signed char. Wenn Sie die Zeichen an übergeben printf Sie alle werden während ihrer Beförderung zu Sign Extended ints. Wenn das erste Bit eine 0 ist, spielt dies keine Rolle, da es mit erweitert wird 0s.
0xAF in binär ist 10101111 Da das erste Bit a ist 1beim Übergeben an printf es wird mit allen erweitert 1s in der Konvertierung zu int Ich mach das 11111111111111111111111110101111der Hex-Wert, den Sie haben.
Lösung: Verwenden unsigned char (Anstatt von char), um zu verhindern, dass die Vorzeichenerweiterung im Anruf auftritt
Alle diese Werte in Ihrem ursprünglichen Beispiel werden vorzeichenerweitert, es ist nur so 0xAF ist der einzige mit a 1 im ersten Bit.
Ein weiteres einfacheres Beispiel für dasselbe Verhalten (Live-Link):
signed char c = 0xAF; // probably gives an overflow warning
int i = c; // extra 24 bits are all 1
assert( i == 0xFFFFFFAF );
Jens
Das liegt daran, dass 0xAF bei der Konvertierung von einem vorzeichenbehafteten Zeichen in eine vorzeichenbehaftete Ganzzahl negativ ist (es ist vorzeichenerweitert) und die %02X format ist für vorzeichenlose Argumente und gibt den konvertierten Wert als aus FFFFFFAF.
Die zusätzlichen Zeichen erscheinen, weil printf %x Wille noch nie Ziffern von einem Wert stillschweigend abschneiden. Werte, die nicht negativ sind, werden ebenfalls vorzeichenerweitert, aber das fügt nur Nullbits hinzu und der Wert passt in 2 Hexadezimalziffern, also printf %02 kann mit einer zweistelligen Ausgabe auskommen.
Beachten Sie, dass es 2 C-Dialekte gibt: einen, wo Plain char signiert ist, und eine, bei der es unsigniert ist. Bei dir ist es unterschrieben. Sie können es mit einer Option ändern, z. B. gcc- und clang-Unterstützung -funsigned-char und -fsigned-char.
Das Ändern der Vorzeichen von char ist keine dauerhafte Lösung …
– Antti Haapala – Слава Україні
9. Mai 2016 um 12:14 Uhr
Grzegorz Szpetkowski
Das printf() ist ein variadisch Funktion und ihre zusätzlichen Argumente (entsprechend mit ... Teil seines Prototyps) unterliegen Standardargument-Promotionsdaher char befördert wird int.
Wie dein char hat unterschrieben1, Zweierkomplement Darstellung wird das höchstwertige Bit auf eins gesetzt 0xAF Element. Während der Heraufstufung wird ein vorzeichenbehaftetes Bit weitergegeben, was zur Folge hat 0xFFFFFFAF von int Typ, wie vermutlich sizeof(int) = 4 bei deiner Umsetzung.
Übrigens rufst du an undefiniertes Verhaltenseit %X Der Formatbezeichner sollte für das Objekt des Typs verwendet werden unsigned int oder zumindest für int mit MSB, das nicht gesetzt ist (dies ist eine übliche, weithin akzeptierte Praxis).
Wie vorgeschlagen, können Sie die Verwendung von eindeutig in Betracht ziehen unsigned char Typ.
1) Die Implementierung kann zwischen signierter und unsignierter Darstellung wählen char. Das ist eher üblich char ist signiert, aber Sie können es nicht für jeden anderen Compiler auf dem Planeten als selbstverständlich ansehen. Einige von ihnen erlauben möglicherweise die Wahl zwischen diesen beiden Modi, wie in Jens Antwort erwähnt.
13637500cookie-checkprintf fügt zusätzliches `FFFFFF` zum Hex-Print aus einem char-Array hinzu [duplicate]yes
Verwenden
unsigned char
Weil0xAF > CHAR_MAX
. Schmuckloschar
ist für Saiten.– cremnr
27. Juni 2015 um 16:01 Uhr
@cremno es hängt tatsächlich vom System ab, einfach
char
kann signiert oder unsigniert sein.– Ryan Haining
27. Juni 2015 um 16:04 Uhr
Standardwarnung: Nicht werfen
void *
(z. B. gegeben vonmalloc()
) zu anderen Zeigern! Ebenfalls:sizeof(char)
wird sich nie von unterscheiden1
denn das ist es, was der Standard nachgeben soll!– zu ehrlich für diese Seite
27. Juni 2015 um 16:57 Uhr
Wenn das Ändern des Typs keine Option ist, werfen Sie ihn einfach:
printf("%02X", (unsigned char)buf[i]);
– KrisWebDev
14. Juni 2016 um 18:46 Uhr
Warum gibt printf beim Drucken von hex nicht nur ein Byte aus?
– phuklv
4. November 2016 um 9:22 Uhr