Domanda

Ho notato che il moderno codice C e C ++ sembra usare size_t invece di int / unsigned int praticamente ovunque - dai parametri per le funzioni della stringa C all'STL. Sono curioso di sapere il motivo di ciò e i benefici che ne derivano.

È stato utile?

Soluzione

Il tipo size_t è il tipo intero senza segno che è il risultato dell'operatore sizeof (e dell'operatore offsetof), quindi è garantito che sia abbastanza grande da contenere la dimensione dell'oggetto più grande del sistema può gestire (ad esempio un array statico di 8 GB).

Il tipo unsigned int può essere maggiore di, uguale o minore di un <=> e il compilatore potrebbe fare ipotesi al riguardo per l'ottimizzazione.

È possibile trovare informazioni più precise nello standard C99, sezione 7.17, una bozza è disponibile su Internet in pdf , o nello standard C11, sezione 7.19, disponibile anche come bozza pdf .

Altri suggerimenti

Il classico C (il primo dialetto di C descritto da Brian Kernighan e Dennis Ritchie in The C Programming Language, Prentice-Hall, 1978) non forniva size_t. Il comitato per gli standard C ha introdotto <=> 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 sul piattaforma di destinazione.

Le dimensioni non dovrebbero mai essere negative e in effetti unsigned int è un tipo senza segno. Inoltre, poiché 4294967295 è 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 un unsigned long int? Potrebbe non essere in grado di contenere numeri abbastanza grandi. In un'implementazione in cui long è 32 bit, il numero più grande che può rappresentare è unsigned long. Alcuni processori, come IP16L32, possono copiare oggetti di dimensioni superiori a unsigned long long byte.

Quindi, chiedi, perché non usare un <=>? Esegue un bilancio delle prestazioni su alcune piattaforme. Lo standard C richiede che un <=> 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'uso di <=> evita questo bilancio delle prestazioni. Secondo questo fantastico articolo , < !> quot; Tipo <=> è un typedef che è un alias per un tipo intero senza segno, in genere <=> o <=>, ma probabilmente anche <=>. Si suppone che ogni implementazione C standard scelga il numero 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. & Quot;

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. È (tipicamente) 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.

Il tipo int invece è sostanzialmente definito come la dimensione del valore intero (con segno) che la macchina host può usare per eseguire l'aritmetica di numeri interi in modo più efficiente. 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 preoccupi dell'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) & Lt; = sizeof (short) & Lt; = sizeof (int) & Lt; = 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').

Il tipo size_t deve essere abbastanza grande da contenere le dimensioni di ogni possibile oggetto. 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

Questo estratto del manuale 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 prima della 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 sia senza segno è 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, unsigned long long non è altro che un typedef per <=>.

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 di default)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top