printf () Formatierung für hex

190

Dies ist eher eine merkwürdige als eine wichtige Frage. Warum wird beim Drucken von Hex als 8-stellige Zahl mit führenden Nullen %#08Xnicht das gleiche Ergebnis angezeigt wie 0x%08X?

Wenn ich versuche, das erstere zu verwenden, wird das 08Formatierungsflag entfernt und es funktioniert nicht nur mit 8.

Wieder war ich nur neugierig.

wsmccusker
quelle
3
Meinst du 0x%.8X? Das wird mit Nullen gefüllt. (Das 0xist nur eine Präambel, aber das wissen Sie wahrscheinlich schon).
WhozCraig

Antworten:

282

Der #Teil gibt Ihnen eine 0xin der Ausgabezeichenfolge. Das 0und die xAnzahl gegen Ihre "8" Zeichen, die im 08Teil aufgeführt sind. Sie müssen nach 10 Zeichen fragen, wenn Sie möchten, dass es gleich ist.

int i = 7;

printf("%#010x\n", i);  // gives 0x00000007
printf("0x%08x\n", i);  // gives 0x00000007
printf("%#08x\n", i);   // gives 0x000007

Das Ändern der Groß- xund Kleinschreibung von wirkt sich auch auf die Schreibweise der ausgegebenen Zeichen aus.

printf("%04x", 4779); // gives 12ab
printf("%04X", 4779); // gives 12AB
Mike
quelle
Die oberste Zeile gibt für mich 14F0x00000007 aus. Das zweite und dritte Werk wie geschrieben.
Quantumpotato
@quantumpotato - Das ist ... seltsam. Die erste und dritte Zeile sind identisch mit Ausnahme der Anzahl der Nullen, die sie erzeugen sollen. Was war Ihr Compiler / System / Codezeile, das dies erzeugt hat? Hatten Sie irgendwelche Zeilen, die mit der gedruckten fortfuhren 14F?
Mike
18
Beachten Sie, dass i = 0;in den verwendeten Versionen %#das 0xPräfix nicht enthalten ist.
Jonathan Leffler
aber wie wäre es mit dem Hex: 0x43A66C31C68491C0 Ich habe Folgendes versucht: __int64 int64 = 0x43A66C31C68491C0; printf_s ("% # 15X% d", int64, int64); Aber die Ausgabe ist 0XC68491C0, nicht 0x43A66C31C68491C0
123iamking
Über das Hex 0x43A66C31C68491C0 oben habe ich es gelöst, die Lösung ist 0x% I64X, nicht% # 15X
123iamking
52

Die "0x" zählt für die acht Zeichen. Du brauchst "%#010x".

Beachten Sie, dass #sich nicht die 0x 0 anhängen - das Ergebnis wird sein , 0000000000- so dass Sie wahrscheinlich sollte eigentlich nur benutzen "0x%08x"sowieso.

Random832
quelle
34

Die %#08XKonvertierung muss vor dem Wert mit erfolgen 0X. das ist vom Standard gefordert. Der Standard enthält keine Hinweise darauf, dass das #Verhalten des 08Teils der Spezifikation geändert werden sollte, außer dass das 0XPräfix als Teil der Länge gezählt wird (daher möchten / müssen Sie es möglicherweise verwenden %#010X. Wenn Sie wie ich Ihr Hex mögen, das als dargestellt wird 0x1234CDEF, dann müssen Sie verwenden 0x%08X, um das gewünschte Ergebnis zu erzielen. Sie könnten verwenden, %#.8Xund das sollte auch die führenden Nullen einfügen.

Probieren Sie Variationen des folgenden Codes aus:

#include <stdio.h>

int main(void)
{
    int j = 0;
    printf("0x%.8X = %#08X = %#.8X = %#010x\n", j, j, j, j);
    for (int i = 0; i < 8; i++)
    {
        j = (j << 4) | (i + 6);
        printf("0x%.8X = %#08X = %#.8X = %#010x\n", j, j, j, j);
    }
    return(0);
}

Auf einem RHEL 5-Computer und auch unter Mac OS X (10.7.5) war die Ausgabe:

0x00000000 = 00000000 = 00000000 = 0000000000
0x00000006 = 0X000006 = 0X00000006 = 0x00000006
0x00000067 = 0X000067 = 0X00000067 = 0x00000067
0x00000678 = 0X000678 = 0X00000678 = 0x00000678
0x00006789 = 0X006789 = 0X00006789 = 0x00006789
0x0006789A = 0X06789A = 0X0006789A = 0x0006789a
0x006789AB = 0X6789AB = 0X006789AB = 0x006789ab
0x06789ABC = 0X6789ABC = 0X06789ABC = 0x06789abc
0x6789ABCD = 0X6789ABCD = 0X6789ABCD = 0x6789abcd

Ich bin ein wenig überrascht über die Behandlung von 0; Ich bin mir nicht 0Xsicher , warum das Präfix weggelassen wird, aber bei zwei separaten Systemen muss es Standard sein. Es bestätigt meine Vorurteile gegen die #Option.


Die Behandlung von Null entspricht dem Standard.

ISO / IEC 9899: 2011 §7.21.6.1 Die fprintfFunktion

¶6 Die Flaggenzeichen und ihre Bedeutung sind:
...
#Das Ergebnis wird in eine "alternative Form" konvertiert. ... Für die x(oder X) Konvertierung wird ein Ergebnis ungleich Null0x (oder 0X) vorangestellt. ...

(Betonung hinzugefügt.)


Beachten Sie, dass bei %#XVerwendung Großbuchstaben für die hexadezimalen Ziffern und 0Xals Präfix verwendet werden. Bei Verwendung von %#xwerden Kleinbuchstaben für die hexadezimalen Ziffern und 0xals Präfix verwendet. Wenn Sie 0xPräfix und Großbuchstaben bevorzugen , müssen Sie diese 0xseparat codieren : 0x%X. Natürlich können bei Bedarf auch andere Formatmodifikatoren hinzugefügt werden.

Verwenden Sie zum Drucken von Adressen die <inttypes.h>Kopfzeile sowie den uintptr_tTyp und das PRIXPTRFormatmakro:

#include <inttypes.h>
#include <stdio.h>

int main(void)
{
    void *address = &address;  // &address has type void ** but it converts to void *
    printf("Address 0x%.12" PRIXPTR "\n", (uintptr_t)address);
    return 0;
}

Beispielausgabe:

Address 0x7FFEE5B29428

Wählen Sie Ihr Gift auf der Länge - ich finde, dass eine Genauigkeit von 12 gut für Adressen auf einem Mac funktioniert, auf dem macOS ausgeführt wird. In Kombination mit der .Angabe der Mindestgenauigkeit (Ziffern) werden Adressen zuverlässig formatiert. Wenn Sie die Genauigkeit auf 16 einstellen, sind die zusätzlichen 4 Ziffern meiner Erfahrung nach auf dem Mac immer 0, aber es gibt sicherlich einen Grund, 16 anstelle von 12 in tragbarem 64-Bit-Code zu verwenden (aber Sie würden 8 für verwenden 32-Bit-Code).

Jonathan Leffler
quelle