Unde este util `%p` cu printf? (Programare, C++, C, Printf)

Moeb a intrebat.

La urma urmei, ambele declarații fac același lucru…

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

De exemplu (cu adrese diferite):

0012FEE0
0012FEE0

Este banal să formatați pointerul așa cum doriți cu %x, , deci există vreo utilizare bună a lui %p opțiune?

Comentarii

  • Folosind „%p” se tipărește adresa variabilei în cauză: „Argumentul pointerului void * este tipărit în hexazecimal (ca și cum ar fi prin %#x sau %#lx).” – user1831086
  • În C++, puteți utiliza (void *) typecast: consultați stackoverflow.com/questions/5657123/… –  > Por kagali-san.
7 răspunsuri
Peter Hosey

Ei nu fac același lucru. Acesta din urmă printf declarație interpretează b ca o unsigned int, , ceea ce este greșit, deoarece b este un pointer.

Pointeri și unsigned ints nu au întotdeauna aceeași dimensiune, astfel încât acestea nu sunt interschimbabile. Atunci când nu au aceeași dimensiune (un caz din ce în ce mai frecvent, pe măsură ce procesoarele și sistemele de operare pe 64 de biți devin tot mai frecvente), %x va imprima doar jumătate din adresă. Pe un Mac (și probabil și pe alte sisteme), acest lucru va fi strica adresa; rezultatul va fi greșit.

Utilizați întotdeauna %p pentru pointeri.

utilizator283145

Comentarii

  • %p va folosi, de asemenea, o reprezentare texturală adecvată pentru pointer pentru platformă. Pe platformele în care este obișnuită reprezentarea pointerului în hexazecimal, acest lucru nu va face o diferență atâta timp cât dimensiunea este corectă, dar pentru o arhitectură segmentată (vă amintiți de DOS?) se poate folosi o reprezentare segment:offset. –  > Por AProgrammer.
  • De asemenea, este necesar să se facă un cast b la void * cu %p acesta este unul dintre puținele cazuri din C în care este nevoie de un cast. –  > Por Alok Singhal.
  • Sindromul „Toată lumea este un VAX!”. –  > Por David Cary.
  • Adăugând la comentariul lui @AlokSinghal: pentru GCC dacă compilați cu -Wextra veți primi avertismente corespunzătoare pentru tipuri incorecte în printf. Pentru a face ca avertismentul să dispară, trebuie să utilizați forma corectă și să faceți cast la void* ceea ce poate fi de ajutor. –  > Por Fred.
dezlegare

Cel puțin pe un sistem care nu este foarte neobișnuit, ele nu se tipăresc la fel:

~/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

Observați cum versiunea cu pointer adaugă un 0x prefix, de exemplu. Folosiți întotdeauna %p, deoarece știe despre dimensiunea pointerilor și despre cum să le reprezinte cel mai bine ca text.

Comentarii

  • „…care nu este foarte neobișnuit”. Frumos 🙂 –  > Por Fizicianul nebun.
Mauritius

Nu puteți depinde de %p afișarea unui 0x prefix. Pe Visual C++, nu o face. Utilizați %#p pentru a fi portabil.

Comentarii

  • Este acest lucru documentat undeva? Nu găsesc nimic despre # folosit împreună cu %p. Am verificat: msdn.microsoft.com/en-us/library/8aky45ct(v=vs.71).aspx cplusplus.com/reference/clibrary/cstdio/printf –  > Por Suma.
  • PC-Lint nu-i place, dar funcționează în Visual Studio. Din nefericire, adaugă în prealabil ‘0X’ și nu ‘0x’, ceea ce face ca valoarea reală să fie greu de citit. Se presupune că acest lucru se datorează unei variante „%P” lipsă. În concluzie, acest specificator de format suferă de problema tuturor implementărilor „dependente de platformă”, și anume că nu poți controla cu adevărat ceea ce vei obține. Eu folosesc „0x%p” cu riscul de a obține un dublu 0x0X la început. Mai degrabă subminează utilizarea acestuia, deoarece știi exact ce vei obține cu %x. –  > Por Andy Krouwel.
  • Acest lucru nu pare să fie deloc portabil, nici măcar între versiunile VC. De exemplu, VS 2013 (12.0.40629.00 update 5) prefixează „0X” pentru „%#p”, dar nu are niciun prefix pentru „%p”. Dar VC 19.00.23506 nu are prefix nici pentru „%p”, nici pentru „%#p”. Apoi, G++ 5.4.0 prefixează cu „0x” atât pentru „%p”, cât și pentru „%#p” (iar utilizarea lui „%#p” dă un avertisment G++). Pe scurt, nu vă puteți baza deloc pe acest format. –  > Por james.
Tronic

Dimensiunea pointerului poate fi ceva diferit de cea a lui int. De asemenea, o implementare ar putea produce o reprezentare mai bună decât simpla reprezentare a valorii hexagonale a adresei atunci când se utilizează %p.

Filip Ekberg

x este un număr întreg hexazecimal fără semn ( 32 Bit )

p este adresa pointerului

A se vedea printf în Manualul de referință C++. Chiar dacă ambele ar scrie la fel, eu aș folosi %p pentru a imprima un pointer.

Comentarii

  • Da, am parcurs deja pagina respectivă. Ceea ce am vrut să știu este de ce ați use %p to print a pointer. Oricum, răspunsul lui Peter Hosey îmi răspunde la îndoiala mea. –  > Por Moeb.
albttx

Atunci când trebuie să depanați, utilizați printf cu %p este foarte utilă. Vedeți 0x0 atunci când aveți o valoare NULL.

Comentarii

  • Pe gcc (4.4.7, cel puțin), o valoare NULL se afișează ca (nil) — inclusiv parantezele. Se pare că există o mulțime de variații specifice implementării în %p –  > Por Steve Friedl.
codaddict

x este utilizat pentru a imprima argumentul pointerului t în hexazecimal.

O adresă tipică atunci când este tipărită folosind %x ar arăta astfel bfffc6e4 iar o adresă sănătoasă tipărită folosind %p ar fi 0xbfffc6e4

Comentarii

  • Nu, %x este utilizată pentru a imprima o valoare de tip unsigned int în hexazecimal. Nu există absolut nicio garanție că unsigned int are aceeași dimensiune ca și void *, , și este o idee proastă să presupunem acest lucru în cod. –  > Por desfaceți.

Tags:,