Lo standard C garantisce che size_tè un tipo che può contenere qualsiasi indice di array. Ciò significa che, logicamente, size_tdovrebbe essere in grado di contenere qualsiasi tipo di puntatore. Ho letto su alcuni siti che ho trovato su Google che questo è legale e / o dovrebbe sempre funzionare:
void *v = malloc(10);
size_t s = (size_t) v;
Quindi, in C99, lo standard ha introdotto i tipi intptr_te uintptr_t, che sono tipi firmati e non firmati garantiti per essere in grado di contenere i puntatori:
uintptr_t p = (size_t) v;
Quindi qual è la differenza tra l'utilizzo di size_te uintptr_t? Entrambi sono senza segno ed entrambi dovrebbero essere in grado di contenere qualsiasi tipo di puntatore, quindi sembrano funzionalmente identici. C'è qualche vero motivo convincente da usare uintptr_t(o meglio ancora, a void *) piuttosto che a size_t, oltre alla chiarezza? In una struttura opaca, in cui il campo sarà gestito solo da funzioni interne, c'è qualche motivo per non farlo?
Allo stesso modo, ptrdiff_tè stato un tipo con segno in grado di contenere le differenze di puntatore e quindi in grado di contenere la maggior parte di qualsiasi puntatore, quindi come si distingue intptr_t?
Tutti questi tipi non servono sostanzialmente versioni banalmente diverse della stessa funzione? Se no, perché? Cosa non posso fare con uno di loro che non posso fare con un altro? In tal caso, perché C99 ha aggiunto due tipi essenzialmente superflui alla lingua?
Sono disposto a ignorare i puntatori alle funzioni, poiché non si applicano al problema attuale, ma sono libero di menzionarli, poiché ho il sospetto che saranno fondamentali per la risposta "corretta".
size_teuintptr_tma che dire diptrdiff_teintptr_t- entrambi non sarebbero in grado di memorizzare lo stesso intervallo di valori su quasi tutte le piattaforme? Perché avere tipi interi di dimensioni puntatore sia firmate che non firmate, in particolare septrdiff_tserve già allo scopo di un tipo intero di dimensioni puntatore firmato.