formato di stringa per intptr_t e uintptr_t

Qual è il formato di stringa per intptr_t e uintptr_t valido per l’architettura a 32 e 64 bit.

MODIFICARE

 warning: format '%x' expects type 'unsigned int', but argument 2 has type "AAA" 

Questo è l’avviso che sto ricevendo a 64 bit ma non a 32 bit.

  intptr_t AAA 

Quello sarebbe le seguenti macro da inttypes.h :

Per printf : PRIdPTR PRIiPTR PRIoPTR PRIuPTR PRIxPTR PRIXPTR

Per scanf : SCNdPTR SCNiPTR SCNoPTR SCNuPTR SCNxPTR

Esempio di utilizzo:

 uinptr_t p = SOME_VALUE; printf("Here's a pointer for you: %" PRIxPTR "\n", p); 

Penso che anche long int non sia sicuro, e dovresti provare long long int , che deve esistere perché stai lavorando su un’architettura a 64 bit e hai già intptr_t .

Su alcune architetture a 64 bit (penso che Microsoft Windows sarebbe così), long int può essere mantenuto in larghezza a 32 bit, per soddisfare l’ipotesi di MS-DOS che short int è sempre a 16 bit e long int sempre 32 -po.

Anche su quelle piattaforms con long int 32 bit, printf("%llx", (unsigned long long)AAA); funzionerebbe. E dovresti considerare più preferibile form printf("%jx", (uintmax_t)AAA); se ansible.

Si noti che per alcuni vecchi compilatori potrebbe essere necessario utilizzare "%Lx" (per GNU C, con cast per unsigned long long ) o "%I64x" (per Visual C ++, con casting per __uint64 ) per interi a 64 bit.

PS %p potrebbe non essere buono in questo caso, perché %p può stampare la bareword 0x prima degli esadecimali e / o stampare un valore con riempimento zero. Se si applicano entrambi, ad esempio, il codice printf("%p\n", (void*)16); stamperà 0x00000010 su piattaforms a 32 bit e 0x0000000000000010 su piattaforms a 64 bit; il poster avrebbe dovuto sperare che solo 10 fossero stampati.

%p dovrebbe funzionare come una sostituzione per %x , poiché uintptr_t è definito come un numero intero senza segno con le stesse dimensioni di un puntatore sulla piattaforma.

EDIT: Sfortunatamente, almeno sul mio compilatore devi lanciare la variabile su (void *). Tuttavia, penso che sia sicuro lanciare uintptr_t su un puntatore.

Sto compilando del codice in un ambiente che per qualche motivo non ha le macro PRI.PTR definite in inttypes.h , e in cui intptr_t è definito come int a 32 bit e long int a 64 bit.

Ho violato gli avvertimenti utilizzando un %li formato %li e convertendo le variabili in long int nei parametri printf . Questo è sicuro in questo ambiente perché un intptr_t non può mai essere più lungo di un long int , come descritto sopra.

Non consiglierei di usare questa soluzione se puoi evitarlo, ma almeno gli avvertimenti sono stati risolti.

 ####################################### CPP type proving code (identifying type by typeid) $ cat typeid.cpp #include  #include  #include  #include  #include  #define name(t) printf("%30s : %s\n", #t, typeid(t).name()) // g++|clang++ -o ./typeid.exe typeid.cpp -m32 && ./typeid.exe // g++|clang++ -o ./typeid.exe typeid.cpp -m64 && ./typeid.exe int main(int argc, char* argv[]) { name(ptrdiff_t); name(intptr_t); name(uintptr_t); return 0; } ####################################### C type proving code (identifying type by _Generic) $ cat typeid.c #include  #include  #include  #include  /* matches the type name of an expression */ #define name_match(e) _Generic((e), \ _Bool: "_Bool", \ char: "char", \ signed char: "signed char", \ unsigned char: "unsigned char", \ short: "short", \ unsigned short: "unsigned short", \ int: "int", \ unsigned int: "unsigned int", \ long: "long", \ unsigned long: "unsigned long", \ long long: "long long", \ unsigned long long: "unsigned long long", \ float: "float", \ double: "double", \ long double: "long double", \ default: "unknown") #define name(t, e) printf("%30s : %s\n", #t, name_match(e)) int main() { ptrdiff_t ptrdiff_v = 0; intptr_t intptr_v = 0; uintptr_t uintptr_v = 0; name(ptrdiff_t, ptrdiff_v); name(intptr_t, intptr_v); name(uintptr_t, uintptr_v); } ####################################### run in arch32 $ clang++ -o ./typeid.exe typeid.cpp -m32 && ./typeid.exe ptrdiff_t : i intptr_t : i uintptr_t : j $ clang -o ./typeid.exe typeid.c -m32 && ./typeid.exe ptrdiff_t : int intptr_t : int uintptr_t : unsigned int result: intptr_t == ptrdiff_t uintptr_t == unsigned ptrdiff_t ####################################### run in arch64 $ clang++ -o ./typeid.exe typeid.cpp -m64 && ./typeid.exe ptrdiff_t : l intptr_t : l uintptr_t : m $ clang -o ./typeid.exe typeid.c -m64 && ./typeid.exe ptrdiff_t : long intptr_t : long uintptr_t : unsigned long result: intptr_t == ptrdiff_t uintptr_t == unsigned ptrdiff_t ####################################### man 3 printf t -- A following integer conversion corresponds to a ptrdiff_t argument. ####################################### conclusion // intptr_t == ptrdiff_t // uintptr_t == unsigned ptrdiff_t // so: // 1) intptr_t has string format %td // 2) uintptr_t has string format %tu #include  #include  int main(int argc, char *argv[]) { intptr_t x = 0; uintptr_t y = 0; scanf("%td %tu", &x, &y); printf("out: %td %tu\n", x, y); return 0; }