Wie drucke ich ein unsigned char in C?

Lesezeit: 7 Minuten

Benutzeravatar von Anton
Anton

Ich versuche, char als positiven Wert zu drucken:

char ch = 212;
printf("%u", ch);

aber ich bekomme:

4294967252

Wie kann ich bekommen 212 in der Ausgabe?

Erklären Sie Ihre ch wie

unsigned char ch = 212 ;

Und Ihr printf wird funktionieren.

  • Sogar mit ch gewechselt zu unsigned char, ist das Verhalten des Codes nicht durch den C-Standard definiert. Dies liegt daran, dass die unsigned char wird zu einem befördert int (in normalen C-Implementierungen), so an int übergeben wird printf für den Spezifizierer %u. Jedoch, %u erwartet ein unsigned intsodass die Typen nicht übereinstimmen und der C-Standard das Verhalten nicht definiert.

    – Eric Postpischil

    1. April 2013 um 13:32 Uhr


  • Ihr Kommentar ist falsch. Der C11-Standard besagt, dass der Konvertierungsbezeichner vom gleichen Typ wie die Funktion sein muss argument selbst, nicht der geförderte Typ. Auf diesen Punkt wird auch in der Beschreibung der speziell eingegangen hh Längenmodifikator: “Das Argument wurde gemäß den Integer-Promotions hochgestuft, aber sein Wert muss vor dem Drucken in ein Zeichen mit Vorzeichen oder ohne Vorzeichen konvertiert werden.”

    – andypea

    13. April 2014 um 23:10 Uhr


  • Funktionierte nur nach expliziter Umwandlung in ` unsigned int` bei der Übergabe an prtinf(). Das Hinzufügen von -std=c11 zum gcc-4.8.4-Befehl, um den Standard durchzusetzen, hatte keine Wirkung.

    – ypx

    23. Oktober 2015 um 9:42 Uhr

  • @EricPostpischil Was genau sagt %d aus? Und was sagt der Spezifizierer %u aus?

    – Suraj Jain

    28. Dezember 2016 um 7:49 Uhr

  • @andrew.punnett: Das Funktionsargument ist der beförderte Wert; es hat den Typ, der sich aus den ganzzahligen Beförderungen ergibt, gemäß C 2011 6.5.2.2 6. Im Fall von hhja, der Standard sagt uns, dass der Typ vor der Beförderung a sein kann signed char oder unsigned char. Es bedeutet, dass die ch wird noch zu einem befördert intaber die Konvertierung %hhu erwartet das. Dies ist jedoch für diese Situation nicht relevant, in der hh ist nicht dabei printf(%u, ch).

    – Eric Postpischil

    29. Dezember 2016 um 12:33 Uhr

Benutzeravatar von Sergey Kalinichenko
Sergej Kalinitschenko

Dies liegt daran, dass in diesem Fall die char Typ ist auf Ihrem System signiert*. In diesem Fall werden die Daten während der Standardkonvertierungen vorzeichenerweitert, während die Daten mit einer variablen Anzahl von Argumenten an die Funktion übergeben werden. Da 212 größer als 0x80 ist, wird es als negativ behandelt, %u interpretiert die Zahl als große positive Zahl:

212 = 0xD4

Wenn es vorzeichenerweitert ist, FFs werden Ihrer Nummer vorangestellt, also wird es

0xFFFFFFD4 = 4294967252

Das ist die Zahl, die gedruckt wird.

Beachten Sie, dass dieses Verhalten spezifisch für Ihre Implementierung ist. Gemäß C99-Spezifikation alle char Typen werden zu (signiert) befördert intweil ein int kann alle Werte von a darstellen charsigniert oder unsigniert:

6.1.1.2: Wenn ein int alle Werte des ursprünglichen Typs darstellen kann, wird der Wert in ein umgewandelt int; andernfalls wird es in ein umgewandelt unsigned int.

Dies führt zum Passieren einer int zu einem Formatbezeichner %udie eine erwartet unsigned int.

Um undefiniertes Verhalten in Ihrem Programm zu vermeiden, fügen Sie explizite Typumwandlungen wie folgt hinzu:

unsigned char ch = (unsigned char)212;
printf("%u", (unsigned int)ch);


* Im Allgemeinen belässt der Standard die Signiertheit von char bis zur Umsetzung. Siehe diese Frage für weitere Details.

  • Diese Antwort ist verworren und ungenau. Die Sätze über die Zeichenerweiterung und die Behandlung von 212 werden ohne Kontext dargestellt, wobei nicht erklärt wird, wo sie zutreffen (der frühere Satz gilt für eine spätere Operation, ganzzahlige Beförderung des char wenn es als Argument verwendet wird, während der spätere Satz für eine frühere Operation gilt, Initialisierung des char mit einem int).

    – Eric Postpischil

    1. April 2013 um 13:12 Uhr

  • Die Aussage, dass 212 als negativ behandelt wird, weil sie größer als 0x80 ist, ist falsch. Initialisieren Sie zunächst eine signierte char mit 212 verursacht in den meisten C-Implementierungen einen ganzzahligen Überlauf, sodass das Verhalten undefiniert ist. In vielen C-Implementierungen führt dies zu einer Kürzung der Zweierkomplementdarstellung von 212 auf acht Bits, was dazu führt, dass die Bits als negativer Wert interpretiert werden, weil das 0x80-Bit gesetzt ist, nicht weil der Anfangswert größer als 0x80 ist (Gegenbeispiele umfassen 0x80 und 0x100).

    – Eric Postpischil

    1. April 2013 um 13:13 Uhr

  • Nach der Initialisierung der chares wird als Argument für verwendet printf. Die ganzzahligen Beförderungen werden durchgeführt, was zu einem Negativ führt int weitergegeben werden printf. Auch hier verwenden viele C-Implementierungen das Zweierkomplement, sodass eine Vorzeichenerweiterung durchgeführt wird, wie diese Antwort sagt. Konvertieren Sie den Wert in unsigned an diesem Punkt würde eine große positive Zahl ergeben. Diese Antwort erklärt jedoch nicht, dass das tatsächliche Verhalten durch den C-Standard nicht definiert ist, da an int wird für einen Bezeichner von übergeben %udie eine erwartet unsigned int.

    – Eric Postpischil

    1. April 2013 um 13:14 Uhr

  • @EricPostpischil Danke für deine Kommentare! Ich habe die Diskrepanz zwischen dem Argument und dem Formatbezeichner übersehen. Dies ist jetzt behoben.

    – Sergej Kalinitschenko

    1. April 2013 um 13:51 Uhr

  • @dasblinkenlight char passt nicht garantiert in den Typ int seit char möglicherweise auf dasselbe Verhalten wie definiert worden sein unsigned char. Nur eine ganze Zahl mit demselben Vorzeichen, aber einem kleineren ganzzahligen Konvertierungsrang hat garantiert einen Wertebereich, der ein Unterbereich des Wertebereichs des anderen Typs ist (Abschnitt 6.2.5 Absatz 8 des C99-Standards). Deswegen, unsigned char könnte theoretisch eine Bandbreite haben, die so groß ist wie unsigned int aufgrund seiner Signiertheit und der ganzzahligen Konvertierungsränge.

    – Wilhelm Grau

    25. Juli 2013 um 21:23 Uhr

Benutzeravatar von Eric Postpischil
Eric Postpischil

Es gibt zwei Fehler in diesem Code. Erstens, in den meisten C-Implementierungen mit signed chares liegt ein Problem vor char ch = 212 weil 212 nicht in ein 8-Bit-Zeichen passt char, und der C-Standard definiert das Verhalten nicht vollständig (es erfordert, dass die Implementierung das Verhalten definiert). Es sollte stattdessen sein:

unsigned char ch = 212;

Zweitens, hinein printf("%u",ch), ch wird zu einem befördert int in normalen C-Implementierungen. Allerdings ist die %u Bezeichner erwartet ein unsigned int, und der C-Standard definiert kein Verhalten, wenn der falsche Typ übergeben wird. Es sollte stattdessen sein:

printf("%hhu", ch);

(Zum %hhu, printf erwartet ein unsigned char das wurde in normalen C-Implementierungen zu befördert int.)

  • Ich würde vorschlagen, static_cast anstelle von Cast im alten Stil zu verwenden

    – Shital Shah

    8. Juni 2016 um 5:23 Uhr

  • @ShitalShah: Die Frage ist mit C gekennzeichnet, nicht mit C++. C hat keinen static_cast-Operator.

    – Eric Postpischil

    29. Dezember 2016 um 12:39 Uhr

  • Ah.. nicht gesehen.

    – Shital Shah

    29. Dezember 2016 um 22:27 Uhr

Falls Sie die Erklärung aus irgendeinem Grund nicht ändern können, haben Sie folgende Möglichkeiten:

char ch = 212;
printf("%d", (unsigned char) ch);

Benutzeravatar von banarun
banarun

Der Zeichenbereich liegt zwischen 127 und -128. Wenn Sie 212 zuweisen, speichert ch -44 (212-128-128) und nicht 212. Wenn Sie also versuchen, eine negative Zahl als unsigned zu drucken, erhalten Sie (MAX-Wert von unsigned int)-abs(number) was in diesem Fall 4294967252 ist

Wenn Sie also 212 so speichern möchten, wie es in ch ist, können Sie ch nur als deklarieren

unsigned char ch;

jetzt ist der Bereich von ch 0 bis 255.

  • “Der Zeichenbereich ist 127 bis -128.” — Nein, der Bereich ist implementierungsdefiniert.

    – Jim Balter

    1. April 2013 um 2:17 Uhr

  • Ich meine, was ich gesagt habe … es war ziemlich klar. Ein Zeichen ist nicht einmal unbedingt 8 Bit lang, geschweige denn unbedingt signiert.

    – Jim Balter

    1. April 2013 um 18:45 Uhr

  • Diese Antwort ist offensichtlich falsch. Der Bereich von Char tut variieren, sind es auf ARM-Plattformen üblicherweise 8 Bit ohne Vorzeichen.

    – Antti Haapala – Слава Україні

    26. Februar 2019 um 7:29 Uhr

Benutzeravatar von Trevor Hickey
Trevor Hickey

Da char ist standardmäßig signed deklariert, was bedeutet, dass der Bereich der Variablen ist

-127 bis +127>

Ihr Wert ist übergelaufen. Um den gewünschten Wert zu erhalten, müssen Sie deklarieren unsigned Modifikator. der Modifikator (unsigned) Bereich ist:

 0 to 255

Um den Bereich eines beliebigen Datentyps zu erhalten, folgen Sie dem Prozess 2^bit Beispiel char8 Bit Länge hat, um seine Reichweite gerade zu bekommen 2 ^(power) 8.

  • “Der Zeichenbereich ist 127 bis -128.” — Nein, der Bereich ist implementierungsdefiniert.

    – Jim Balter

    1. April 2013 um 2:17 Uhr

  • Ich meine, was ich gesagt habe … es war ziemlich klar. Ein Zeichen ist nicht einmal unbedingt 8 Bit lang, geschweige denn unbedingt signiert.

    – Jim Balter

    1. April 2013 um 18:45 Uhr

  • Diese Antwort ist offensichtlich falsch. Der Bereich von Char tut variieren, sind es auf ARM-Plattformen üblicherweise 8 Bit ohne Vorzeichen.

    – Antti Haapala – Слава Україні

    26. Februar 2019 um 7:29 Uhr

1416650cookie-checkWie drucke ich ein unsigned char in C?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy