Hintergrund: Ich habe eine Reihe von Skripten, die Protokolldateien analysieren, indem sie nach Hex-Zahlen suchen, indem sie das führende “0x” finden. Unsere eingebettete C-Bibliothek wurde auf ein neues printf umgestellt. Das neue printf ist standardkonformer als unser vorheriges und meine Skripte sind kaputt gegangen.
Auf einer Linux-Box:
#include <stdio.h>
int main( void )
{
printf( "%#010x\n", 0 );
printf( "%#010x\n", 1 );
return 0;
}
Ausgabe (mit glibc) ist:
0000000000
0x00000001
Ausgabe auf unserer Firmware war:
0x00000000
0x00000001
Aus printf(3), beim ‘#’-Flag-Zeichen: “Bei x- und X-Konvertierungen wird einem Ergebnis ungleich Null die Zeichenfolge “0x” (oder “0X” für X-Konvertierungen) vorangestellt.”
ich bin neugierig warum. Warum nicht ein führendes 0x für ein Argument mit Nullwert, ohne die C-Standarddokumente zu durchsuchen oder Mittagessen für die Mitglieder des Standardkomitees zu kaufen?
Der Standard scheint so geschrieben zu sein:
-
%#x
und %#o
versuchen Sie sicherzustellen, dass die Ausgabe korrekt analysiert werden kann, indem Sie verwenden strtol
mit base = 0
.
-
In diesen Fällen ist die #
Flagge fügt hinzu so wenige zusätzliche Zeichen wie möglich. Beispielsweise wird 0 als gedruckt 0
weil es nicht nötig ist, das Extra hinzuzufügen 0x
. Dies ist sehr sinnvoll, wenn Sie dies tun nicht Geben Sie die minimale Feldbreite und das Auffüllen mit 0 an.
-
Wenn Sie hinzufügen wollten 0x
immer, man könnte oft einfach so etwas schreiben wie 0x%x
. Somit %#x
scheint nützlich zu sein nur in den speziellen Fällen, in denen Sie wirklich wollen die besondere Behandlung von 0. Aber das Voranstellen von 0x
funktioniert nicht gut mit Standard-Feldbreitenbezeichnern, z. B.) 0x%12x
wird rechtsbündig durch Leerzeichen zwischen den 0x- und Hex-Ziffern ausgerichtet, was in diesem Fall wahrscheinlich nicht erwünscht ist. Für diesen Fall wäre ein extra Vorbereitungsdurchgang mit sprintf erforderlich, also ein Hex-String wie "0x2ac2"
kann mit so etwas wie Leerraum rechtsbündig ausgerichtet werden printf( "%12s", hexstr);
Glücklicherweise rechtfertigt mit 0
anstatt Leerzeichen mit so etwas wie printf( "0x%012x", hexstr);
funktioniert wie erwartet und erzeugt gültige Hexadezimalziffern für einen Parser.
Nun der Weg %#x
spezifiziert ist, um isoliert zu arbeiten, macht viel Sinn. Und so etwas wie %010x
spezifiziert ist, um isoliert zu arbeiten, macht viel Sinn. Sie kombinieren diese beiden Modifikatoren, und das Endergebnis ist wohl seltsam. Für eine andere Anwendung, wie das automatische Generieren von sauberem C-Code zum Initialisieren von Tabellen 0,
statt 0x0
ist kein Thema.
Aber es muss nicht kombiniert werden %#x
und %010x
. Du könntest einfach schreiben 0x%08x
zu tun, was du willst.
Wilde Vermutung: 0 ist 0, unabhängig von der Basis, also muss es nicht angegeben werden.
– Daniel Fischer
14. Dezember 2011 um 23:32 Uhr
Es ist erwähnenswert, dass Sie das Verhalten von erhalten können stets einschließlich einer führenden
0x
durch Schreiben"0x%08x"
wohingegen das standardmäßig beschriebene Verhalten schwieriger aus einer Bibliothek zu bekommen wäre stets enthalten die führenden0x
. Vielleicht optimierte das Normenkomitee eher für einen schwer zu erreichenden Fall als für den absolut häufigsten Fall? (Natürlich kann man sich nicht ändern"%#10x"
zu"0x%8x"
aber andererseits ist es schwer vorstellbar, dass jemand sehen will0x0
ohne Nullauffüllung.)– ruach
14. Dezember 2011 um 23:36 Uhr
Es gibt keine Erwähnung davon in der C89 Begründung (HTML) oder im C99 Begründung (PDF).
– Keith Thompson
15. Dezember 2011 um 0:06 Uhr