Lo standard C garantisce che size_t
sia un tipo che può contenere qualsiasi indice di matrice. Ciò significa che, logicamente, size_t
dovrebbe essere in grado di contenere qualsiasi tipo di puntatore. Ho letto su alcuni siti che ho trovato sul Googles che questo è legale e/o dovrebbe funzionare sempre:size_t vs. uintptr_t
void *v = malloc(10);
size_t s = (size_t) v;
Allora nel C99, lo standard introdotto i intptr_t
e uintptr_t
tipi, che sono firmati e non firmati tipi garantiti per essere in grado di tenere i puntatori:
uintptr_t p = (size_t) v;
Allora, qual è la differenza tra l'utilizzo size_t
e uintptr_t
? Entrambi sono senza segno, ed entrambi dovrebbero essere in grado di contenere qualsiasi tipo di puntatore, in modo che sembrino funzionalmente identici. C'è qualche ragione convincente per usare (o meglio ancora, uno void *
) piuttosto che uno size_t
, diverso dalla chiarezza? In una struttura opaca, dove il campo sarà gestito solo da funzioni interne, c'è qualche ragione per non farlo?
Allo stesso modo, ptrdiff_t
è stato un tipo firmato in grado di contenere le differenze di puntatore e quindi in grado di contenere la maggior parte dei puntatori, quindi come è distinto da intptr_t
?
Non tutti questi tipi servono fondamentalmente versioni diverse della stessa funzione? Se no, perché? Cosa non posso fare con uno di loro che non posso fare con un altro? Se è così, perché C99 ha aggiunto due tipi essenzialmente superflui alla lingua?
Sono disposto a ignorare i puntatori di funzione, in quanto non si applicano al problema corrente, ma sentitevi liberi di menzionarli, poiché ho un sospetto furtivo che saranno al centro della risposta "corretta".
Questo, insieme ai numerosi altri che sono saltati alla stessa conclusione, spiega la differenza tra 'size_t' e' uintptr_t', ma per quanto riguarda 'ptrdiff_t' e' intptr_t' - entrambi non sarebbero in grado di memorizzare lo stesso intervallo di valori su quasi tutte le piattaforme? Perché hanno entrambi i tipi di numeri interi con segno e senza segno del puntatore, in particolare se 'ptrdiff_t' serve già allo scopo di un tipo di intero con segno del puntatore. –
La frase chiave è "on * quasi * qualsiasi piattaforma", @Chris. Un'implementazione è libera di limitare i puntatori all'intervallo 0xf000-0xffff - ciò richiede un intptr_t a 16 bit ma solo un ptrdiff_t a 12/13 bit. – paxdiablo
@Chris, solo per i puntatori _in uno stesso array_ è ben definito per fare la differenza. Quindi, su esattamente le stesse architetture segmentate a 16 bit (l'array deve vivere all'interno di un singolo segmento ma due diversi array possono essere in segmenti diversi) i puntatori devono essere 4 byte ma il puntatore ** differenze ** potrebbe essere 2 byte! –