sizeof style: sizeof (type) o sizeof variable?

17

Ho visto due stili di usare sizeof per le operazioni relative alla memoria (come in memset o malloc ):

  • sizeof(type) e
  • sizeof variable o sizeof(variable)

Quale preferiresti, o useresti un mix dei due stili e quando useresti ogni stile? Quali sono i pro e i contro di ogni stile e quando li usi?

Ad esempio, posso vedere il seguente paio di situazioni in cui uno stile aiuta e l'altro no:

Quando si ottiene il puntatore indiretto errato:

type *var;
...
memset(var, 0, sizeof var);    /* oops */

Quando il tipo cambia:

new_type var;    /* changed from old_type to new_type */
...
memset(&var, 0, sizeof(old_type));    /* oops */
    
posta congusbongus 11.06.2013 - 04:02
fonte

6 risposte

29

I perfer% sizeof(variable) su sizeof(type) . Prendere in considerazione:

int a1;
float a2;
memset(&a1,0,sizeof(a1));
memset(&a2,0,sizeof(a2));

vs.

int a1;
float a2;
memset(&a1,0,sizeof(int));
memset(&a2,0,sizeof(float));

Nel primo caso, è facile verificare che le dimensioni giuste vengano passate a memset . Nel secondo caso, è necessario rivedere costantemente le sezioni superiore e inferiore per assicurarsi di essere coerenti.

    
risposta data 11.06.2013 - 05:06
fonte
8

La preferenza (come sempre) è quella di riflettere le tue intenzioni il più direttamente possibile.

L'intenzione è di operare contro la memoria di una variabile esistente? In questo caso, utilizza sizeof(variable) , in quanto mostra il più fedelmente possibile che è la memoria stessa della variabile che ti interessa.

L'intenzione di eseguire alcuni calcoli sul tipo, ad esempio per determinare la quantità di memoria da allocare per una nuova istanza? In tal caso, utilizza sizeof(type) .

Cioè, preferisco

struct foo *bar;
bar = (struct foo *) malloc(sizeof(struct foo));

su

bar = (struct foo *) malloc(sizeof(*bar));

come nel secondo caso sembra come se stessi cercando di accedere a una variabile che non esiste ancora.

D'altra parte, preferisco

char Buffer[256];
memset(Buffer, 0, sizeof(Buffer));

su

char Buffer[256];
memset(Buffer, 0, 256 * sizeof(char));

poiché l'intenzione è chiaramente di azzerare il contenuto della variabile, quindi è la variabile con cui dovremmo operare. Cercando di usare i metadati di tipo confondiamo semplicemente le cose, qui.

    
risposta data 11.06.2013 - 17:33
fonte
2

Preferisco di gran lunga sizeof(type) oltre sizeof variable . Anche se ti costringe a preoccuparti di più del tipo e ad apportare ulteriori modifiche, ti aiuta a evitare gli errori di puntatore indiretto, che rango tra la causa più comune di bug in C .

Non mi preoccuperei molto dei bug in cui il tipo in sizeof(type) viene modificato; ogni volta che si modifica il tipo di una variabile, è necessario eseguire una scansione rapida per vedere dove viene utilizzata tale variabile e se è necessario modificare qualsiasi istruzione sizeof(type) . Anche se c'è sempre una possibilità di sbagliare, ha un rischio molto inferiore rispetto agli errori di puntatore indiretto.

Un vantaggio di sizeof variable è per gli array, ma in pratica ho scoperto che gli array di passaggio come coppie di first / len sono molto più comuni (nel qual caso basta usare la lunghezza), in più è anche molto facile ottenere la dimensione errata a causa del decadimento della matrice / puntatore, come in questo esempio:

ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) {
  memcpy( mat, src, sizeof( src ) );    /* NOT the same as 3*3*sizeof(float) */
}
    
risposta data 11.06.2013 - 04:02
fonte
0

L'obiettivo è rimuovere la ridondanza. Se si utilizza sizeof per un'operazione correlata a una variabile, ovviamente si dovrà tenerne conto nella dimensione di. Sì, puoi rovinare come nel primo esempio, ma la cura non è il tipo di utilizzo, ma * var, che corrisponde correttamente all'obiettivo.

Per mitigare tali problemi è usuale usare macro, template e strumenti simili addestrati per il caso d'uso piuttosto che sizeo nudo.

Vedi il mio CLEAR macro utilizzato esclusivamente al posto di memset nudo. Salvato il mio culo più volte in caso di errore di scrittura indiretto o quando un contenuto di struct ha raccolto un vettore o una stringa ...

    
risposta data 11.06.2013 - 11:16
fonte
0

La logica aziendale definisce la tua scelta.

  1. Se il tuo codice fa riferimento a una particolare variabile e senza questa variabile il tuo codice non ha senso - scegli sizeof(var)

  2. Se il codice riguarda un insieme di variabili con un tipo particolare, scegli sizeof(type) . Di solito è necessario se si dispone di un typedef che definisce molte variabili elaborate in modo diverso in base al loro tipo (ad es. Serializzazione). Non si può sapere quali di queste variabili rimarranno nelle versioni future del codice, quindi la scelta del tipo come argomento è logicamente corretta. Anche la modifica di tale typedef non influirà sulla dimensione della linea.

risposta data 20.05.2014 - 13:15
fonte
-1

A seconda dello scopo sizeof (variabile) potrebbe essere la soluzione migliore. In questo modo, è possibile modificare il tipo di variabile se necessario, senza correggere tutte le voci per il tipo. Ma ancora, dipende dal tuo obiettivo.

    
risposta data 11.06.2013 - 12:37
fonte

Leggi altre domande sui tag