Frage

In C, ich möchte printf verwenden Zeiger anzeigen zu lassen, und so, dass sie richtig ausgerichtet ist, würde Ich mag sie mit 0s aufzufüllen.

Meine Vermutung war, dass der richtige Weg, dies zu tun war:

printf("%016p", ptr);

Dies funktioniert, aber diese gcc beschwert sich mit der folgenden Meldung an:

warning: '0' flag used with ‘%p’ gnu_printf format

Ich habe es ein bisschen gegoogelt und die folgenden Threads zum gleichen Thema, ist aber nicht wirklich eine Lösung geben.

http://gcc.gnu.org/ml/ gcc-bugs / 2003-05 / msg00484.html

es Lesen, scheint es, dass der Grund, warum gcc beschwert ist, dass die Syntax schlug ich vor, nicht in C99 definiert ist. Aber ich kann nicht anders zu finden scheinen die gleiche Sache in einem Standard-genehmigten Art und Weise zu tun.

Hier ist also die doppelte Frage:

  • Ist mein Verständnis richtig, dass dieses Verhalten nicht durch den C99-Standard definiert ist?
  • Wenn ja, ist es eine Standard genehmigt, tragbare Art und Weise, dies zu tun?
War es hilfreich?

Lösung

#include <inttypes.h>

#include <stdint.h>

printf("%016" PRIxPTR "\n", (uintptr_t)ptr);

, aber es wird den Zeiger in der Implementierung definierte Art und Weise (sagt DEAD:BEEF für 8086 segmentierten Modus) nicht drucken.

Andere Tipps

Verwendung:

#include <inttypes.h>

printf("0x%016" PRIXPTR "\n", (uintptr_t) pointer);

oder ein andere Variante des Makros aus diesen Header verwenden.

Beachten Sie auch, dass einige Implementierungen von printf() eine ‚0x‘ drucken vor dem Zeiger; andere dies nicht tun (und beide korrekt sind nach dem C-Standard).

Die einzige portable Art und Weise Zeigerwerte zu drucken, ist die "%p" Spezifizierer zu verwenden, die die Implementierung definiert Ausgabe erzeugt. (Umstellung auf uintptr_t und PRIxPTR mit wahrscheinlich zu arbeiten, aber (a) uintptr_t wurde in C99 eingeführt, so dass einige Compiler können es nicht unterstützen, und (b) es ist nicht in C99 existiert sogar garantiert (es nicht ein Integer-Typ sein könnte groß genug, um alle möglichen Zeigerwerte zu halten.

So verwenden "%p" mit sprintf() (oder snprintf(), wenn Sie es haben) in eine Zeichenfolge zu drucken, und dann mit führenden Leerzeichen die Zeichenfolge padding drucken.

Ein Problem ist, dass es keine wirklich gute Möglichkeit ist die maximale Länge der Zeichenfolge durch "%p" erzeugt zu bestimmen.

Dies ist zwar unbequem (obwohl natürlich Sie es in einer Funktion wickeln können). Wenn Sie nicht 100% Portabilität benötigen, habe ich nie verwendet ein System, um den Zeiger wurden Gießen das Ergebnis unsigned long und Druck "0x%16lx" mit nicht funktionieren würde. [ UPDATE : Ja, ich habe. 64-Bit-Windows hat 64-Bit-Zeiger und 32-Bit-unsigned long.] (Sie können auch "0x%*lx" verwenden und die Breite berechnen, wahrscheinlich so etwas wie sizeof (void*) * 2. Wenn Sie wirklich paranoid sind, können Sie für Systeme zu berücksichtigen, wo CHAR_BIT > 8, so dass Sie‘ ll pro Byte mehr als 2 hex-Ziffern erhalten.)

Diese Antwort ist ähnlich dem früher angegebenen in https://stackoverflow.com/a/1255185/1905491 sondern nimmt auch die möglichen Breiten berücksichtigen (wie umrissen von https://stackoverflow.com/a/6904396/1905491 die ich habe nicht erkennen, bis meine Antwort unten, damit er gemacht wurde;). Die snipped folgenden wird Zeiger als 8 0-geben Hexzeichen auf sane * Maschinen gedruckt werden, wo sie von 32 Bits dargestellt werden kann, 16 auf 64b und 4 auf 16b Systemen.

#include <inttypes.h>
#define PRIxPTR_WIDTH ((int)(sizeof(uintptr_t)*2))

printf("0x%0*" PRIxPTR, PRIxPTR_WIDTH, (uintptr_t)pointer);

die Verwendung des Sternchen Beachten Sie die Breite durch das nächste Argument zu holen, die in C99 ist (wahrscheinlich vor?), Aber das ist ziemlich selten „in the wild“ gesehen. Das ist viel besser als die p Umwandlung verwenden, da die letztere ist die Implementierung definiert.

* Der Standard ermöglicht uintptr_t als das Minimum größer zu sein, aber ich nehme an, sich keine Implementierung, die nicht das Minimum nicht verwendet.

Es ist leicht zu lösen, wenn Sie den Mauszeiger auf einen langen Typen umgewandelt. Das Problem ist, wird dies nicht auf allen Plattformen arbeitet, wie es ein Zeiger übernimmt in einem langen passen kann, und daß ein Zeiger in 16 Zeichen (64 Bits) dargestellt werden. Dies ist jedoch wahr auf den meisten Plattformen.

so wäre es geworden:

printf("%016lx", (unsigned long) ptr);

Wie Sie Ihren Link bereits vermuten lässt, ist das Verhalten nicht definiert. Ich glaube nicht, dass es ein tragbarer Weg, dies als% p zu tun, sich auf der Plattform, auf der Sie arbeiten abhängt. Man könnte natürlich einfach den Zeiger auf einen int gegossen und es in hex angezeigt werden:

printf("0x%016lx", (unsigned long)ptr);

Vielleicht wird dies interessant sein (von einer 32-Bit-Windows-Maschine, mit mingw):

rjeq@RJEQXPD /u
$ cat test.c
#include <stdio.h>

int main()
{
    char c;

    printf("p: %016p\n", &c);
    printf("x: %016llx\n", (unsigned long long) (unsigned long) &c);

    return 0;
}

rjeq@RJEQXPD /u
$ gcc -Wall -o test test.c
test.c: In function `main':
test.c:7: warning: `0' flag used with `%p' printf format

rjeq@RJEQXPD /u
$ ./test.exe
p:         0022FF77
x: 000000000022ff77

Wie Sie sehen können, werden die% p Version Pads mit Nullen auf die Größe eines Zeigers, und dann Leerzeichen auf die angegebene Größe, während mit% x und Abgüsse (die Modelle und Formatbezeichner sind sehr portabel) nur Nullen.

Beachten Sie, dass, wenn sich der Zeiger druckt mit dem Präfix „0x“, müssten Sie ersetzen „% 018p“ zu kompensieren.

Ich verwende% x in der Regel Zeiger angezeigt werden soll. Ich nehme an, dass nicht tragbar ist auf 64-Bit-Systeme, aber es funktioniert für 32-Bitters in Ordnung.

Ich werde zu sehen, interessiert sein, was dort Antworten sind für tragbare Lösungen , da Darstellung Zeiger ist nicht gerade tragbar.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top