Macro di lunghezza dell’array comune per C?

Ho visto diversi macro per la lunghezza dell’array fluttuante:

Da questa domanda :

  • #define length(array) (sizeof(array)/sizeof(*(array)))
  • #define ARRAY_LENGTH(array) (sizeof((array))/sizeof((array)[0]))
  • #define SIZE(array, type) (sizeof(array) / (sizeof(type))

E il _countof :

 #define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0])) 

Quello che mi piacerebbe sapere è:

  1. Qual è la differenza tra quelli che usano array[0] e *array ?
  2. Perché dovrebbe essere preferibile?
  3. Differiscono in C ++?

Ecco una versione C migliore (dal progetto Chromium di Google):

 #define COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) 

Migliora la array[0] o la versione *array usando 0[array] , che è equivalente array[0] su array semplici, ma non riuscirà a compilare se array presenta come un tipo C ++ che sovraccarica l’ operator[]() .

La divisione causa un’operazione di divisione per zero (che dovrebbe essere rilevata in fase di compilazione poiché è un’espressione costante in fase di compilazione) per molte (ma non tutte) situazioni in cui un puntatore viene passato come parametro array .

Vedi Esiste una funzione standard in C che restituirebbe la lunghezza di un array? per ulteriori dettagli.

C’è un’opzione migliore per il codice C ++. Vedi Tempo di compilazione sizeof_array senza utilizzare una macro per i dettagli.

  1. Qual è la differenza tra quelli che usano array [0] e * array?
  2. Perché dovrebbe essere preferibile?
  3. Differiscono in C ++?

(1) Nessuna differenza in C. Nessuna differenza per un vero array raw in C ++.

(2) Nessun motivo tecnico per preferire l’uno o l’altro, ma i neofiti potrebbero essere confusi dalla dereferenziazione puntatore.

(3) In C ++ normalmente non si usa la macro, perché è molto pericolosa. Se passi un puntatore invece di un vero array raw, il codice verrà compilato ma restituirà un risultato errato. Quindi in C ++ dovresti / dovresti usare un modello di funzione, come …

 #include  typedef ptrdiff_t Size; template< class Type, Size n > Size countOf( Type (&)[n] ) { return n; } 

Questo accetta solo l’array raw reale come argomento.

Fa parte di una triade di funzioni startOf , endOf e countOf che è molto conveniente definire in modo che possano essere applicati sia agli array raw che ai contenitori di librerie standard. Per quanto ne so, questa triade fu identificata per la prima volta da Dietmar Kuehl. In C ++ 0x startOf e endOf saranno probabilmente disponibili come std::begin e std::end .

Saluti e hth.,

1) Niente, il valore di un array è un puntatore al suo primo elemento. Quindi * array == array [0]
2) Preferenza personale
3) No

Si noti che questa macro non funzionerà se viene chiamata all’interno di una funzione in cui l’array viene passato come parametro nella funzione. Questo perché l’object array ha passato “decadimenti” in un puntatore piuttosto che in una copia profonda.