Risposte:
Il size_t
tipo è il tipo intero senza segno che è il risultato sizeof
dell'operatore (e offsetof
dell'operatore), quindi è garantito che sia abbastanza grande da contenere le dimensioni dell'oggetto più grande che il sistema può gestire (ad esempio, un array statico di 8 Gb).
Il size_t
tipo può essere maggiore di, uguale o minore di un unsigned int
e il compilatore potrebbe fare ipotesi al riguardo per l'ottimizzazione.
È possibile trovare informazioni più precise nella norma C99, sezione 7.17, una bozza di cui è disponibile su Internet in formato pdf , o nella norma C11, sezione 7.19, disponibile anche come bozza in pdf .
size_t
può rappresentare! In caso contrario, chi lo fa?
Classic C (il primo dialetto di C descritto da Brian Kernighan e Dennis Ritchie in The C Programming Language, Prentice-Hall, 1978) non lo ha fornito size_t
. Il comitato per le norme C introdotto size_t
per eliminare un problema di portabilità
Spiegato in dettaglio su embedded.com (con un ottimo esempio)
In breve, size_t
non è mai negativo e massimizza le prestazioni perché è stato tipizzato come il tipo intero senza segno che è abbastanza grande - ma non troppo grande - per rappresentare la dimensione dell'oggetto più grande possibile sulla piattaforma di destinazione.
Le dimensioni non dovrebbero mai essere negative e in effetti size_t
è un tipo senza segno. Inoltre, poiché size_t
è senza segno, è possibile memorizzare numeri grandi circa il doppio rispetto al tipo con segno corrispondente, poiché è possibile utilizzare il bit di segno per rappresentare la grandezza, come tutti gli altri bit nell'intero senza segno. Quando guadagniamo un altro bit, stiamo moltiplicando l'intervallo di numeri che possiamo rappresentare per un fattore di circa due.
Quindi, chiedi, perché non usare solo un unsigned int
? Potrebbe non essere in grado di contenere numeri abbastanza grandi. In un'implementazione in cui unsigned int
sono presenti 32 bit, il numero più grande che può rappresentare è 4294967295
. Alcuni processori, come IP16L32, possono copiare oggetti più grandi di 4294967295
byte.
Quindi, chiedi, perché non usare un unsigned long int
? Esegue un bilancio delle prestazioni su alcune piattaforme. Lo standard C richiede che long
occupi almeno 32 bit. Una piattaforma IP16L32 implementa ogni lunghezza a 32 bit come una coppia di parole a 16 bit. Quasi tutti gli operatori a 32 bit su queste piattaforme richiedono due istruzioni, se non di più, perché lavorano con i 32 bit in due blocchi a 16 bit. Ad esempio, lo spostamento di una lunghezza di 32 bit richiede in genere due istruzioni macchina: una per spostare ogni blocco di 16 bit.
L'utilizzo size_t
evita questo bilancio delle prestazioni. Secondo questo fantastico articolo , "Tipo size_t
è un typedef che è un alias per un tipo intero senza segno, in genere unsigned int
o unsigned long
, ma forse anche unsigned long long
. Ogni implementazione Standard C dovrebbe scegliere l'intero senza segno che è abbastanza grande - ma non più grande del necessario-- per rappresentare la dimensione dell'oggetto più grande possibile sulla piattaforma di destinazione. "
unsigned int
lattina e varia da un sistema all'altro. Deve essere almeno 65536
, ma è comunemente 4294967295
e potrebbe essere 18446744073709551615
(2 ** 64-1) su alcuni sistemi.
unsigned char
). Lo standard non sembra contenere la stringa '65535' o '65536' ovunque, e '32.767' si verifica solo (1,9: 9) in una nota come possibile rappresentabile più grande numero intero int
; nessuna garanzia è data nemmeno che INT_MAX
non può essere più piccola di quella!
Il tipo size_t è il tipo restituito dall'operatore sizeof. È un numero intero senza segno in grado di esprimere la dimensione in byte di qualsiasi intervallo di memoria supportato sul computer host. È (in genere) correlato a ptrdiff_t in quanto ptrdiff_t è un valore intero con segno tale che sizeof (ptrdiff_t) e sizeof (size_t) sono uguali.
Quando scrivi il codice C dovresti sempre usare size_t ogni volta che hai a che fare con intervalli di memoria.
D'altra parte, il tipo int è sostanzialmente definito come la dimensione del valore intero (con segno) che la macchina host può usare per eseguire in modo più efficiente l'aritmetica dei numeri interi. Ad esempio, su molti computer di tipo PC più vecchi il valore sizeof (size_t) sarebbe 4 (byte) ma sizeof (int) sarebbe 2 (byte). L'aritmetica a 16 bit era più veloce dell'aritmetica a 32 bit, sebbene la CPU potesse gestire uno spazio di memoria (logico) fino a 4 GiB.
Usa il tipo int solo quando ti interessa l'efficienza poiché la sua precisione effettiva dipende fortemente sia dalle opzioni del compilatore che dall'architettura della macchina. In particolare lo standard C specifica i seguenti invarianti: sizeof (char) <= sizeof (short) <= sizeof (int) <= sizeof (long) non ponendo altre limitazioni alla rappresentazione effettiva della precisione disponibile per il programmatore per ciascuno di questi tipi primitivi.
Nota: NON è lo stesso di Java (che in realtà specifica la precisione dei bit per ciascuno dei tipi 'char', 'byte', 'short', 'int' e 'long').
size_t
è in grado di rappresentare la dimensione di ogni singolo oggetto (es: numero, matrice, struttura). L'intero intervallo di memoria può superaresize_t
size_t
- Spero che non lo intendi. Il più delle volte non ci occupiamo di array in cui conta anche la cardinalità dello spazio degli indirizzi + portabilità. In questi casi avresti preso size_t
. In ogni altro caso prendi gli indici da numeri interi (firmati). Perché la confusione (che arriva senza preavviso) derivante da comportamenti insospettati di underflow di non firmati è più comune e peggiore dei problemi di portabilità che possono insorgere negli altri casi.
Digitare size_t deve essere abbastanza grande per memorizzare le dimensioni di qualsiasi oggetto possibile. Unsigned int non deve soddisfare quella condizione.
Ad esempio, nei sistemi a 64 bit int e unsigned int possono avere una larghezza di 32 bit, ma size_t deve essere abbastanza grande per memorizzare numeri maggiori di 4G
size_t
dovrebbe essere così grande se il compilatore potesse accettare un tipo X tale che sizeof (X) produrrebbe un valore maggiore di 4G. La maggior parte dei compilatori rifiuterebbe typedef unsigned char foo[1000000000000LL][1000000000000LL]
, ad esempio , e foo[65536][65536];
potrebbe anche essere legittimamente rifiutata se superasse un limite documentato definito dall'implementazione.
Questo estratto dal manuale di glibc 0.02 può anche essere rilevante quando si ricerca l'argomento:
Esiste un potenziale problema con il tipo size_t e le versioni di GCC precedenti alla versione 2.4. ANSI C richiede che size_t sia sempre un tipo senza segno. Per compatibilità con i file di intestazione dei sistemi esistenti, GCC definisce size_t in stddef.h' to be whatever type the system's
sys / types.h 'lo definisce. La maggior parte dei sistemi Unix che definiscono size_t in `sys / types.h ', lo definiscono un tipo con segno. Alcuni codici nella libreria dipendono dal fatto che size_t è un tipo senza segno e non funzionerà correttamente se è firmato.
Il codice della libreria GNU C che prevede che size_t non sia firmato è corretto. La definizione di size_t come tipo firmato è errata. Prevediamo che nella versione 2.4, GCC definirà sempre size_t come un tipo senza segno e fixincludes' script will massage the system's
sys / types.h 'per non essere in conflitto con questo.
Nel frattempo, risolviamo questo problema dicendo a GCC di utilizzare esplicitamente un tipo senza segno per size_t durante la compilazione della libreria GNU C. `configure 'rileverà automaticamente quale tipo GCC usa per size_t organizza sovrascriverlo se necessario.
Se il mio compilatore è impostato su 32 bit, size_t
non è altro che un typedef per unsigned int
. Se il mio compilatore è impostato su 64 bit, size_t
non è altro che un typedef per unsigned long long
.
unsigned long
per entrambi i casi su alcuni sistemi operativi.
size_t è la dimensione di un puntatore.
Quindi in 32 bit o il modello ILP32 (intero, lungo, puntatore) comune size_t è 32 bit. e in 64 bit o il comune modello LP64 (long, pointer) size_t è 64 bit (gli interi sono ancora 32 bit).
Esistono altri modelli ma questi sono quelli che usano g ++ (almeno per impostazione predefinita)
size_t
non ha necessariamente le stesse dimensioni di un puntatore, anche se comunemente lo è. Un puntatore deve essere in grado di puntare a qualsiasi posizione nella memoria; size_t
deve solo essere abbastanza grande da rappresentare la dimensione del singolo oggetto più grande.