Qual è la differenza tra size_t e int in C ++?

In diversi esempi C ++ vedo un uso del tipo size_t dove avrei usato un int semplice. Qual è la differenza e perché size_t dovrebbe essere migliore?

Dalla Wikipedia amichevole :

I file di intestazione stdlib.h e stddef.h definiscono un tipo di dati chiamato size_t che viene utilizzato per rappresentare la dimensione di un object. Le funzioni di libreria che prendono dimensioni si aspettano che siano di tipo size_t e l’operatore sizeof valuti a size_t.

Il tipo effettivo di size_t dipende dalla piattaforma; un errore comune è quello di assumere size_t è lo stesso di unsigned int, che può portare a errori di programmazione, in particolare quando le architetture a 64 bit diventano più prevalenti.

Inoltre, controlla Perché size_t è importante

size_t è il tipo utilizzato per rappresentare le dimensioni (come indica il nome). La sua piattaforma (e anche potenzialmente l’implementazione) dipende e dovrebbe essere utilizzata solo per questo scopo. Ovviamente, rappresentando una dimensione, size_t non è firmata. Molte funzioni di stdlib, tra cui malloc, sizeof e varie funzioni per le operazioni su stringhe usano size_t come un tipo di dati.

Un int è firmato per impostazione predefinita, e anche se la sua dimensione dipende anche dalla piattaforma, sarà un 32 bit fisso sulla maggior parte delle macchine moderne (e sebbene size_t sia 64 bit su architettura a 64 bit, int resterà a 32 bit di lunghezza su quelle architetture).

Per riassumere: usa size_t per rappresentare la dimensione di un object e int (o long) negli altri casi.

È perché size_t può essere qualsiasi cosa diversa da un int (forse una struct). L’idea è che disaccoppia il suo lavoro dal tipo sottostante.

Il tipo size_t è definito come il tipo integrale senza segno dell’operatore sizeof . Nel mondo reale, vedrete spesso int definito come 32 bit (per retrocompatibilità) ma size_t definito come 64 bit (in modo da poter dichiarare array e strutture con dimensioni superiori a 4 GiB) su piattaforms a 64 bit. Se un long int è anche 64-bit, questo è chiamato la convenzione LP64; se long int è 32 bit ma long long int e pointers 64 bit, è LLP64. Si potrebbe anche ottenere il contrario, un programma che utilizza istruzioni a 64 bit per la velocità, ma i puntatori a 32 bit per risparmiare memoria. Inoltre, int è firmato e size_t non è firmato.

C’erano storicamente un certo numero di altre piattaforms in cui gli indirizzi erano più larghi o più brevi della dimensione nativa di int . In effetti, negli anni ’70 e all’inizio degli anni ’80, questo era più comune: tutti i popolari microcomputer a 8 bit avevano registri a 8 bit e indirizzi a 16 bit, e la transizione tra 16 e 32 bit produceva anche molte macchine che aveva indirizzi più ampi dei loro registri. Di tanto in tanto vedo ancora domande su Borland Turbo C per MS-DOS, la cui modalità di memoria enorme aveva indirizzi a 20 bit memorizzati in 32 bit su una CPU a 16 bit (ma che poteva supportare il set di istruzioni a 32 bit dell’80386); il Motorola 68000 aveva un ALU a 16 bit con registri e indirizzi a 32 bit; c’erano mainframe IBM con indirizzi 15-bit, 24-bit o 31-bit. È inoltre ansible vedere diverse dimensioni di ALU e bus di indirizzo nei sistemi incorporati.

Ogni volta che int è minore di size_t e si tenta di memorizzare la dimensione o l’offset di un file o di un object molto grande in un unsigned int , esiste la possibilità che possa traboccare e causare un bug. Con un int , c’è anche la possibilità di ottenere un numero negativo. Se un int o unsigned int è più ampio, il programma funzionerà correttamente ma sprecherà memoria.

In genere, se si desidera la portabilità, è necessario utilizzare il tipo corretto per lo scopo. Un sacco di persone raccomandano di usare la matematica firmata anziché quella non firmata (per evitare bug fastidiosi come 1U < -3 ). A tale scopo, la libreria standard definisce ptrdiff_t in come tipo firmato del risultato della sottrazione di un puntatore da un altro.

Detto questo, una soluzione alternativa potrebbe essere quella di controllare tutti gli indirizzi e gli offset rispetto a INT_MAX e 0 o INT_MIN come appropriato, e triggersre gli avvisi del compilatore sul confronto delle quantità firmate e non firmate nel caso in cui manchi qualsiasi. Dovresti sempre, sempre, controllare sempre gli accessi al tuo array per overflow in C comunque.

La definizione di SIZE_T è disponibile all’indirizzo: https://msdn.microsoft.com/en-us/library/cc441980.aspx e https://msdn.microsoft.com/en-us/library/cc230394.aspx

Incollare qui le informazioni richieste:

SIZE_T è un ULONG_PTR rappresenta il numero massimo di byte a cui un puntatore può puntare.

Questo tipo è dichiarato come segue:

 typedef ULONG_PTR SIZE_T; 

Un ULONG_PTR è un tipo lungo senza segno utilizzato per la precisione del puntatore. Viene utilizzato quando si esegue il cast di un puntatore a un tipo lungo per eseguire l’aritmetica del puntatore.

Questo tipo è dichiarato come segue:

 typedef unsigned __int3264 ULONG_PTR;