Der% x-Formatbezeichner mit einem unsignierten Zeichen in C [doppelt]

8

Ich bin über das folgende Beispielprogramm gestolpert und verstehe es nicht genau:

%Vor%

Es wird gedruckt:

%Vor%

Das Problem ist die letzte Spalte. Da es nicht signiert ist, würde ich erwarten, dass es nur 2 Stellen in jeder Spalte ausgibt. ~n erzeugt ein unsigniertes Zeichen als Ergebnis, aber es scheint, als würde es in einen vorzeichenbehafteten 32-Bit-Wert umgewandelt und um den %5x -Spezifizierer erweitert.

Wie ist das möglich, was geht hier vor?

    
Robert S. Barnes 25.08.2011, 10:37
quelle

4 Antworten

10

Integertypen werden bei arithmetischen Operationen aktiviert (dies hat übrigens nichts mit printf zu tun).

Also zum Beispiel

%Vor%

Ganzzahlige Werbung verursacht verschiedene Probleme:

%Vor%

Die beiden Möglichkeiten, Dinge zu kürzen, sind Casting und Masken. Verwenden Sie, was immer Sie bevorzugen.

%Vor%

Ganzzahlige Werbung findet nicht immer statt, und es ist nicht die einzige Art von impliziter Besetzung. Es ist auch ein bisschen subtil und die genauen Regeln sind schwer zu merken. Sie müssen sich nur dann wirklich darum kümmern, wenn Sie mit 64-Bit-Zahlen arbeiten, denn 1U << 32 könnte am Ende 0 oder 1 oder etwas ganz anderes sein. (Es ist oft 1 auf x86).

    
Dietrich Epp 25.08.2011, 10:44
quelle
2

Das Problem ist, dass es zu einem int hochgestuft wird, wenn Sie es - wie in Dietrichs Antwort - in printfs Varags übergeben, wenn Sie es negieren.

Leider müssen Sie es auf ein Byte abziehen, um es zu übergeben, d. h. (~n & 0xff) .

    
Rup 25.08.2011 10:40
quelle
0

Meine Vermutung ist, dass all Ihre übergebenen char s als 32-Bit-Ganzzahlen interpretiert werden, aber in den ersten 4 Fällen ist die Ausgabe die gleiche. Nur im letzten zeigt es sein hässliches Gesicht:)

Sie müssen alle anderen Bits ausblenden, um ein zeichenartiges Ergebnis wie in den ersten 4 Beispielen zu erhalten.

    
Constantinius 25.08.2011 10:42
quelle
0

1) Sie haben die Breite als% 5x angegeben, aber es gibt eine Regel bezüglich des Breitenbezeichners in C. Wenn die Breite der zu druckenden Zahl größer ist als die zugewiesene Breite, wird der Breitenspezifizierer ignoriert. So kann in der letzten Spalte der Zahleninhalt nicht in der zugewiesenen Breite 5 dargestellt werden, so dass die Breitengrenze ignoriert wurde. Warum die Breite größer als 5 ist, habe ich im 3. Punkt erläutert. Jetzt im 2. Punkt sage ich% x vs unsigned char.

2) Siehe Freund, den Sie die Variable 'n' als vorzeichenloses Zeichen deklariert haben, aber Sie haben% x verwendet, das für vorzeichenloses hexadezimales int steht. Zum Zeitpunkt des Druckens wird also der Wert von n gefördert oder technisch können Sie typecasted als vorzeichenlose hexadezimale Ganzzahl angeben. Dies gilt nicht nur für unsigned char und% x. Sie sollten Dirrerent-Kombinationen auf Ihrem Compiler genau so ausprobieren int a = -5; printf ("% d% u", a, a); Jetzt erhalten Sie -5 by% d und für% u erhalten Sie eine andere Interpretation abhängig von Compiler-Eigenschaften, ob es 16-Bit oder 32-Bit ist. jetzt, wenn du es versuchst unsigned int a = -5; printf ("% d% u", a, a); Ergebnis wird immer noch dasselbe wie vorher sein. Im ersten Fall schreibst du int a = 5 und im zweiten Fall schreibst du unsigned int = 5, aber das Ergebnis hängt von der Interpretation ab, also ist das wie folgt.

Hier geht es um Typecasting oder Sie können über die Interpretation durch den Compiler sagen. Wenn Sie% x sagen, sagen Sie selbst zum Compiler, dass es als vorzeichenloses hexadezimales int interpretiert wird. Ich hoffe, es ist jetzt klar, für den Fall, dass es nicht ich vorschlagen, dass Sie kleine verschiedene Programme und das auch auf viele Compiler ausführen. Programme wie int x = 7; printf ("% f" x); etc etc .. Sie werden sicherlich den Punkt bekommen. Jetzt erkläre ich die aus der letzten Spalte, warum es wie fffffffe ist.

3) Wir betrachten den ersten Durchlauf der Schleife. hier ist n = 0x1. In einem 32-Bit-Compiler wird es im Speicher als 0000 0001 dargestellt, da char 1 Byte Speicher zur Verfügung gestellt wird. Danach, wenn Sie es als vorzeichenlose hexadezimale Ganzzahl eingeben, ist die Interpertation in einem 32-Bit-Compiler 0000 0000 0000 0000 0000 0000 0000 0001 Nun, wenn Sie int n = 1 deklarieren oder Sie deklarieren unsigned int n = 1 oder deklarieren Sie int n = 0x1. die Darstellung wird gleich sein. Selbst wenn Sie unsigned char n = 1 verwenden, ist die Ziffer ganz rechts 1 und alle anderen null, obwohl die Anzahl der Nullen geringer sein kann. In Ihrer Schleifenanweisung, indem Sie% x angeben, weisen Sie den Compiler an, den Inhalt als unsigniertes hexadezimales int zu interpretieren, damit der Compiler den Platz als hexadezimales Feld zur Verfügung stellt und Sie diese Operation "~ n" ausführen 1111 1111 1111 1111 1111 1111 1111 1110. (Achtung - Denken Sie daran, dass printf ("% d", ~ n); Fall anders als printf ("% d", n ++); im n ++ Fall der Wert der Variablen im Speicher wird aber auch aktualisiert, aber die Verwendung von printf ("% d", ~ n) ist ähnlich mit printf ("% d", n + 8).) Wie bei dieser neuen Darstellung von Bits sind alle Bits 1 außer ganz rechts. Jetzt, wenn es gedruckt wird, wird es wie fffffffe gedruckt. einfach!

4) Sie haben "geschrieben, aber es scheint, als würde es in einen 32-Bit-Wert mit Vorzeichen umgewandelt und um den% 5x-Spezifizierer erweitert." hmmm% x ist nicht für vorzeichenbehaftetes hexadezimales int% x ist für vorzeichenloses hexadezimales int, also kein Punkt, der davon ausgeht, dass das Minuszeichen abgeschnitten wurde.

5) In deinem Programm hast du '~ n' benutzt, überprüfe einfach verschiedene Versionen wie '- ~ n' oder  "-n". das ist für den experimentellen Zweck.

    
melyfony 25.08.2011 18:06
quelle

Tags und Links