Perché memset () sta inizializzando erroneamente int?

Perché l’output del seguente programma 84215045 ?

 int grid[110]; int main() { memset(grid, 5, 100 * sizeof(int)); printf("%d", grid[0]); return 0; } 

memset imposta ciascun byte del buffer di destinazione sul valore specificato. Sul tuo sistema, un int è quattro byte, ognuno dei quali è 5 dopo la chiamata a memset . Pertanto, la grid[0] ha il valore 0x05050505 (esadecimale), che è 84215045 in decimale.

Alcune piattaforms forniscono API alternative a memset che scrivono pattern più ampi nel buffer di destinazione; ad esempio, su OS X o iOS, puoi usare:

 int pattern = 5; memset_pattern4(grid, &pattern, sizeof grid); 

per ottenere il comportamento che ti sembra di aspettarti. Quale piattaforma stai prendendo di mira?

In C ++, dovresti semplicemente usare std::fill_n :

 std::fill_n(grid, 100, 5); 
 memset(grid, 5, 100 * sizeof(int)); 

Stai impostando 400 byte, a partire dalla (char*)grid e finendo a (char*)grid + (100 * sizeof(int)) , al valore 5 (i cast sono necessari qui perché memset occupa in byte , mentre il puntatore aritmetico offerte in objects .

84215045 in esadecimale è 0x05050505 ; dato che int (sulla tua piattaforma / compilatore / etc.) è rappresentato da quattro byte, quando lo stampi ottieni “quattro cinque”.

memset riguarda l’impostazione di byte, non valori. Uno dei molti modi per impostare i valori dell’array in C ++ è std::fill_n :

 std::fill_n(grid, 100, 5); 

Non usare memset.

Si imposta ogni byte [] della memoria sul valore di 5. Ogni int è 4 byte lungo [5][5][5][5] , che il compilatore interpreta correttamente come 5 * 256 * 256 * 256 + 5 * 256 * 256 + 5 * 256 + 5 = 84215045. Invece, utilizzare un ciclo for, che non richiede nemmeno sizeof (). In generale, sizeof () significa che stai facendo qualcosa nel modo più duro.

 for(int i=0; i<110; ++i) grid[i] = 5; 

Bene, il memset scrive i byte, con il valore selezionato. Pertanto un int sarà simile a questo:

 00000101 00000101 00000101 00000101 

Che viene quindi interpretato come 84215045.

Non hai effettivamente detto cosa vuoi che faccia il tuo programma.

Supponendo che si desideri impostare ognuno dei primi 100 elementi della grid su 5 (ignorando la discrepanza tra 100 e 110 ), basta fare ciò:

 for (int i = 0; i < 100; i ++) { grid[i] = 5; } 

Capisco che tu sia preoccupato per la velocità, ma la tua preoccupazione è probabilmente malriposta. Da un lato, memset() è probabilmente ottimizzato e quindi più veloce di un semplice ciclo. D'altra parte, l'ottimizzazione dovrebbe consistere nella scrittura di più di un byte alla volta, che è ciò che fa questo ciclo. D'altra parte, memset() è comunque un loop; scrivere esplicitamente il ciclo piuttosto che seppellirlo in una chiamata di funzione non lo cambia. D'altro canto, anche se il ciclo è lento, non è probabile che importi; concentrati sulla scrittura di codice chiaro e pensa a ottimizzarlo se le misurazioni effettive indicano che c'è un problema di prestazioni significativo.

Hai passato molti ordini di grandezza più a scrivere la domanda che il tuo computer spenderà la grid impostazione.

Infine, prima che finisca le mani (troppo tardi!), Non importa quanto velocemente memset() sia se non fa quello che vuoi. (Non impostare affatto la grid è ancora più veloce!)

Se scrivi man memset sulla tua shell, ti dice che

void * memset(void *b, int c, size_t len)

Una semplice spiegazione inglese di ciò sarebbe, esso riempie una stringa di byte b di lunghezza len con ogni byte un valore c .

Per il tuo caso,

 memset(grid, 5, 100 * sizeof(int)); 

Poiché sizeof(int)==4 , quindi i pezzi di codice sopra indicati assomigliavano a:

 for (int i=0; i<100; i++) grid[i]=0x05050505; 

O

 char *grid2 = (char*)grid; for (int i=0; i<100*sizeof(int); i++) grid2[i]=0x05; 

Stamperebbe 84215045

Ma nella maggior parte del codice C, vogliamo inizializzare un pezzo di blocco di memoria sul valore zero.

  • tipo di char -> \0 o NUL
  • tipo int -> 0
  • float type -> 0.0f
  • double tipo -> 0.0
  • tipo di puntatore -> nullptr

E sia gcc o clang ecc. I compilatori moderni possono prenderti cura di questo automaticamente per te.

 // variadic length array (VLA) introduced in C99 int len = 20; char carr[len]; int iarr[len]; float farr[len]; double darr[len]; memset(carr, 0, sizeof(char)*len); memset(iarr, 0, sizeof(int)*len); memset(farr, 0, sizeof(float)*len); memset(darr, 0, sizeof(double)*len); for (int i=0; i 

Ma attenzione, la commissione C ISO non impone tali definizioni, è specifica per il compilatore.

Poiché il memset scrive i byte, di solito lo uso per impostare un array int a zero come:

 int a[100]; memset(a,0,sizeof(a)); 

oppure puoi usarlo per impostare un array di caratteri, poiché un char è esattamente un byte:

 char a[100]; memset(a,'*',sizeof(a)); 

inoltre, un array int può anche essere impostato su -1 con memset:

 memset(a,-1,sizeof(a)); 

Questo perché -1 è 0xffffffff in int, ed è 0xff in char (un byte).

Questo codice è stato testato. Ecco un modo per memset di una matrice “Integer” su un valore compreso tra 0 e 255.

 MinColCost=new unsigned char[(Len+1) * sizeof(int)]; memset(MinColCost,0x5,(Len+1)*sizeof(int)); memset(MinColCost,0xff,(Len+1)*sizeof(int));