2010-03-03 18 views
44

Dopo tutto, entrambe queste affermazioni fanno la stessa cosa ...Dove è `% p` utile con printf?

int a = 10; 
int *b = &a; 
printf("%p\n",b); 
printf("%08X\n",b); 

Per esempio (con indirizzi diversi):

0012FEE0 
0012FEE0 

È banale per formattare il puntatore, se lo desideri con %x, così c'è un buon uso dell'opzione %p?

+1

Utilizzando '% p' ​​di stampare l'indirizzo della variabile in questione, "L'argomento void * pointer sono stampati in esadecimale (come per% # x o% # lx)." –

+0

In C++, è possibile utilizzare typecast (void *): vedi http://stackoverflow.com/questions/5657123/how-to-simulate-printfs-p-format-when-using-stdcout –

risposta

111

Non fanno la stessa cosa. La seconda istruzione printf interpreta b come unsigned int, che è errato, poiché b è un puntatore.

I puntatori e gli unsigned int s non hanno sempre le stesse dimensioni, quindi non sono intercambiabili. Quando non hanno le stesse dimensioni (un caso sempre più comune, poiché le CPU e i sistemi operativi a 64 bit diventano più comuni), %x stamperà solo metà dell'indirizzo. Su un Mac (e probabilmente su altri sistemi), lo corrisponderà a rovinando l'indirizzo; l'output sarà sbagliato.

Utilizzare sempre %p per i puntatori.

+12

% p utilizzerà anche un'adeguata rappresentazione strutturale per il puntatore della piattaforma. Sulle piattaforme in cui è comune rappresentare il puntatore in esadecimale, questo non farà differenza se la dimensione è corretta ma per un'architettura segmentata (ricordate DOS?) Potrebbe utilizzare un segmento: rappresentazione offset. – AProgrammer

+8

Uno deve anche lanciare 'b' a' void * 'con il formato'% p' - questa è una delle poche istanze in C in cui è necessario un cast. –

+1

"Tutto il mondo è un VAX!" sindrome. –

2

x è senza segno intero esadecimale (32 bit)

p è puntatore di indirizzo

Vedi printf on the C++ Reference. Anche se entrambi scrivessero lo stesso, userei %p per stampare un puntatore.

+0

sì, ho già passato attraverso quella pagina.Quello che volevo sapere era perché dovresti usare% p per stampare un puntatore. Ad ogni modo, la risposta di Peter Hosey risponde al mio dubbio. – Moeb

4

La dimensione del puntatore può essere diversa da quella di int. Inoltre, un'implementazione potrebbe produrre risultati migliori della semplice rappresentazione del valore esadecimale dell'indirizzo quando si utilizza %p.

-1

x viene utilizzato per stampare l'argomento del puntatore t in esadecimale.

Un indirizzo tipico quando stampate utilizzando %x sarebbe simile bfffc6e4 e l'indirizzo sana stampato utilizzando %p sarebbe 0xbfffc6e4

+0

No, '% x' è usato per stampare un valore di tipo' unsigned int' in esadecimale. Non c'è assolutamente alcuna garanzia che 'unsigned int' abbia la stessa dimensione di' void * ', ed è una cattiva idea assumerlo nel codice. – unwind

7

Almeno su un sistema che non è molto raro, che non stampare lo stesso:

~/src> uname -m 
i686 
~/src> gcc -v 
Using built-in specs. 
Target: i686-pc-linux-gnu 
[some output snipped] 
gcc version 4.1.2 (Gentoo 4.1.2) 
~/src> gcc -o printfptr printfptr.c 
~/src> ./printfptr 
0xbf8ce99c 
bf8ce99c 

Nota come la versione puntatore aggiunge un prefisso 0x, ad esempio. Usa sempre% p poiché conosce la dimensione dei puntatori e come rappresentarli al meglio come testo.

5

Non è possibile dipendere da %p con prefisso 0x. Su Visual C++, non è così. Utilizzare %#p per essere portatili.

+1

È documentato da qualche parte? Non riesco a trovare nulla su # usato insieme a% p. Ho controllato: http://msdn.microsoft.com/en-us/library/8aky45ct(v=vs.71).aspx http://www.cplusplus.com/reference/clibrary/cstdio/printf/ – Suma

+0

PC -Lint non gli piace, ma funziona in Visual Studio. Sfortunatamente antepone '0X' non '0x', rendendo difficile la lettura del valore reale. Presumibilmente ciò è dovuto a una variante mancante di "% P". Tutto sommato, questo specificatore di formato soffre del problema di tutte le implementazioni 'dipendenti dalla piattaforma', che non è possibile controllare realmente ciò che si otterrà. Io uso '0x% p' a rischio di ottenere un doppio 0x0X all'inizio. Piuttosto mina il suo utilizzo, perché sai esattamente cosa stai ottenendo con% x. –

0

Quando è necessario eseguire il debug, l'uso printf con %p opzione è veramente utile. Vedete 0x0 quando avete un valore NULL.