int short - Cosa è size_t in C?





long c++ (10)


Se sei il tipo empirico ,

echo | gcc -E -xc -include 'stddef.h' - | grep size_t

Uscita per GCC 4.8 Ubuntu 14.04 64 bit:

typedef long unsigned int size_t;

Si noti che stddef.h è fornito da GCC e non glibc in src/gcc/ginclude/stddef.h in GCC 4.2.

Interessanti presenze C99

  • malloc accetta size_t come argomento, quindi determina la dimensione massima che può essere allocata.

    E poiché viene anche restituito da sizeof , penso che limiti la dimensione massima di qualsiasi array.

    Vedi anche: Qual è la dimensione massima di un array in C?

Mi sto confondendo con size_t in C. So che viene restituito dall'operatore sizeof . Ma di cosa si tratta esattamente? È un tipo di dati?

Diciamo che ho un ciclo for :

for(i = 0; i < some_size; i++)

Dovrei usare int i; o size_t i; ?




size_t e int non sono intercambiabili. Ad esempio su Linux a 64 bit size_t una dimensione di 64 bit (cioè sizeof(void*) ) ma int è a 32 bit.

Si noti inoltre che size_t non è firmato. Se hai bisogno di una versione firmata allora c'è ssize_t su alcune piattaforme e sarebbe più rilevante per il tuo esempio.

Come regola generale suggerirei di usare int per la maggior parte dei casi generali e usare solo size_t / ssize_t quando ce n'è una specifica necessità (con mmap() per esempio).




size_t è un tipo senza segno. Quindi, non può rappresentare alcun valore negativo (<0). Lo usi quando conti qualcosa, e sei sicuro che non possa essere negativo. Ad esempio, strlen() restituisce una dimensione_t perché la lunghezza di una stringa deve essere almeno 0.

Nell'esempio, se l'indice del ciclo sarà sempre maggiore di 0, potrebbe essere opportuno utilizzare size_t o qualsiasi altro tipo di dati non firmato.

Quando usi un oggetto size_t , devi assicurarti che in tutti i contesti in cui viene usato, inclusa l'aritmetica, vuoi valori non negativi. Ad esempio, supponiamo di avere:

size_t s1 = strlen(str1);
size_t s2 = strlen(str2);

e vuoi trovare la differenza tra le lunghezze di str2 e str1 . Non puoi fare:

int diff = s2 - s1; /* bad */

Questo perché il valore assegnato a diff sarà sempre un numero positivo, anche quando s2 < s1 , perché il calcolo viene eseguito con tipi senza segno. In questo caso, a seconda di quale sia il tuo caso d'uso, potresti stare meglio usando int (o long long ) per s1 e s2 .

Ci sono alcune funzioni in C / POSIX che potrebbero / dovrebbero usare size_t , ma non per motivi storici. Ad esempio, il secondo parametro di fgets dovrebbe essere idealmente size_t , ma è int .




Dalla mia comprensione, size_t è un intero unsigned una dimensione di bit abbastanza grande da contenere un puntatore dell'architettura nativa.

Così:

sizeof(size_t) >= sizeof(void*)



size_t è un tipo di dati intero senza segno. Sui sistemi che usano la libreria GNU C, questo sarà unsigned int o unsigned long int. size_t è comunemente usato per l'indicizzazione degli array e il conteggio dei cicli.




size_t è un tipo che può contenere qualsiasi indice di array.

A seconda dell'implementazione, può essere una delle seguenti:

unsigned char

unsigned short

unsigned int

unsigned long

unsigned long long

Ecco come size_t è definito in stddef.h della mia macchina:

typedef unsigned long size_t;



In generale, se stai iniziando a 0 e procedendo verso l'alto, usa sempre un tipo senza segno per evitare un overflow che ti porta in una situazione con valore negativo. Questo è di fondamentale importanza, perché se i limiti dell'array sono inferiori al massimo del ciclo, ma il massimo del tuo loop è maggiore del massimo del tuo tipo, ti avvolgeremo in negativo e potresti riscontrare un errore di segmentazione (SIGSEGV ). Quindi, in generale, non usare mai int per un ciclo che inizia da 0 e va verso l'alto. Usa un non firmato.




size_t o qualsiasi tipo di unsigned potrebbe essere visto come variabile di ciclo poiché le variabili di ciclo sono generalmente maggiori o uguali a 0.

Quando usiamo un oggetto size_t , dobbiamo assicurarci che in tutti i contesti che viene usato, inclusa l'aritmetica, desideriamo solo valori non negativi. Ad esempio, il seguente programma darebbe sicuramente il risultato inaspettato:

// C program to demonstrate that size_t or
// any unsigned int type should be used 
// carefully when used in a loop

#include<stdio.h>
int main()
{
const size_t N = 10;
int a[N];

// This is fine
for (size_t n = 0; n < N; ++n)
a[n] = n;

// But reverse cycles are tricky for unsigned 
// types as can lead to infinite loop
for (size_t n = N-1; n >= 0; --n)
printf("%d ", a[n]);
}

Output
Infinite loop and then segmentation fault



Dal momento che nessuno lo ha ancora menzionato, il significato linguistico primario di size_t è che l'operatore sizeof restituisce un valore di quel tipo. Allo stesso modo, il significato principale di ptrdiff_t è che sottrarre un puntatore da un altro produrrà un valore di quel tipo. Le funzioni di libreria che accettano lo fanno perché consentono a tali funzioni di funzionare con oggetti le cui dimensioni superano UINT_MAX su sistemi in cui tali oggetti potrebbero esistere, senza costringere i chiamanti a sprecare il codice passando un valore maggiore di "unsigned int" su sistemi in cui il tipo più grande sarebbe sufficiente per tutti gli oggetti possibili.




Diversi suggerimenti:

  1. Inserisci inserti / aggiornamenti in una transazione.
  2. Per le versioni precedenti di SQLite: si consideri una modalità di journal meno paranoica ( pragma journal_mode ). C'è NORMAL , e poi c'è OFF , che può aumentare significativamente la velocità di inserimento se non sei troppo preoccupato che il database possa essere danneggiato se il sistema operativo si arresta in modo anomalo. Se l'applicazione si blocca, i dati dovrebbero andare bene. Notare che nelle versioni più recenti, le impostazioni OFF/MEMORY non sono sicure per i crash a livello di applicazione.
  3. Anche giocare con le dimensioni della pagina fa la differenza ( PRAGMA page_size ). Avere dimensioni di pagina più grandi può rendere le letture e le scritture un po 'più veloci mentre le pagine più grandi sono conservate in memoria. Si noti che verrà utilizzata più memoria per il database.
  4. Se hai indici, considera la possibilità di chiamare CREATE INDEX dopo aver eseguito tutti i tuoi inserimenti. Questo è significativamente più veloce della creazione dell'indice e quindi dei tuoi inserimenti.
  5. Bisogna stare molto attenti se si ha accesso simultaneo a SQLite, poiché l'intero database è bloccato al termine delle scritture e, sebbene siano possibili più lettori, le scritture verranno bloccate. Questo è stato leggermente migliorato con l'aggiunta di un WAL nelle nuove versioni di SQLite.
  6. Approfitta del risparmio di spazio ... i database più piccoli diventano più veloci. Ad esempio, se si hanno coppie di valori chiave, provare a rendere la chiave INTEGER PRIMARY KEY se possibile, che sostituirà la colonna del numero di riga univoco implicito nella tabella.
  7. Se si utilizzano più thread, è possibile provare a utilizzare la cache della pagina condivisa , che consente di condividere le pagine caricate tra thread, evitando costose chiamate I / O.
  8. Non usare !feof(file) !

Ho anche fatto domande simili here e here .





c int size-t