Come posso determinare la dimensione del mio array in C?

Come posso determinare la dimensione del mio array in C?

Cioè, il numero di elementi che la matrice può contenere?

    Sintesi:

    int a[17]; size_t n = sizeof(a)/sizeof(a[0]); 

    Per determinare la dimensione della matrice in byte, è ansible utilizzare l’operatore sizeof :

     int a[17]; size_t n = sizeof(a); 

    Sul mio computer, gli int sono lunghi 4 byte, quindi n è 68.

    Per determinare il numero di elementi nell’array, possiamo dividere la dimensione totale dell’array in base alla dimensione dell’elemento dell’array. Puoi farlo con il tipo, come questo:

     int a[17]; size_t n = sizeof(a) / sizeof(int); 

    e ottenere la risposta corretta (68/4 = 17), ma se il tipo di a modifica si avrebbe un brutto bug se si è dimenticato di cambiare anche la sizeof(int) .

    Quindi il divisore preferito è sizeof(a[0]) , la dimensione dell’elemento zeroeth dell’array.

     int a[17]; size_t n = sizeof(a) / sizeof(a[0]); 

    Un altro vantaggio è che ora è ansible parametrizzare facilmente il nome dell’array in una macro e ottenere:

     #define NELEMS(x) (sizeof(x) / sizeof((x)[0])) int a[17]; size_t n = NELEMS(a); 

    La dimensione del modo è quella giusta se si ha a che fare con array non ricevuti come parametri. Un array inviato come parametro a una funzione viene considerato come un puntatore, quindi sizeof restituirà la dimensione del puntatore, anziché quella dell’array.

    Pertanto, all’interno delle funzioni questo metodo non funziona. Invece, passa sempre un parametro addizionale size_t size indica il numero di elementi nella matrice.

    Test:

     #include  #include  void printSizeOf(int intArray[]); void printLength(int intArray[]); int main(int argc, char* argv[]) { int array[] = { 0, 1, 2, 3, 4, 5, 6 }; printf("sizeof of array: %d\n", (int) sizeof(array)); printSizeOf(array); printf("Length of array: %d\n", (int)( sizeof(array) / sizeof(array[0]) )); printLength(array); } void printSizeOf(int intArray[]) { printf("sizeof of parameter: %d\n", (int) sizeof(intArray)); } void printLength(int intArray[]) { printf("Length of parameter: %d\n", (int)( sizeof(intArray) / sizeof(intArray[0]) )); } 

    Output (in un SO Linux a 64 bit):

     sizeof of array: 28 sizeof of parameter: 8 Length of array: 7 Length of parameter: 2 

    Output (in un sistema operativo Windows a 32 bit):

     sizeof of array: 28 sizeof of parameter: 4 Length of array: 7 Length of parameter: 1 

    Vale la pena notare che sizeof non aiuta quando si ha a che fare con un valore dell’array decaduto su un puntatore: anche se punta all’inizio di un array, al compilatore è uguale a un puntatore a un singolo elemento di quel array. Un puntatore non “ricorda” altro sull’array utilizzato per inizializzarlo.

     int a[10]; int* p = a; assert(sizeof(a) / sizeof(a[0]) == 10); assert(sizeof(p) == sizeof(int*)); assert(sizeof(*p) == sizeof(int)); 

    La dimensione del “trucco” è il modo migliore che conosco, con un piccolo ma (per me, questo è un grosso cruccio) importanti cambiamenti nell’uso delle parentesi.

    Come chiarisce la voce di Wikipedia, la dimensione di C non è una funzione; è un operatore . Pertanto, non richiede una parentesi attorno al suo argomento, a meno che l’argomento non sia un nome di tipo. È facile da ricordare, poiché rende l’argomento simile a un’espressione cast, che utilizza anche parentesi.

    Quindi: se hai il seguente:

     int myArray[10]; 

    Puoi trovare il numero di elementi con codice come questo:

     size_t n = sizeof myArray / sizeof *myArray; 

    Questo, per me, è molto più semplice dell’alternativa con parentesi. Preferisco anche l’uso dell’asterisco nella parte destra della divisione, poiché è più conciso dell’indicizzazione.

    Naturalmente, anche questo è tutto in fase di compilazione, quindi non è necessario preoccuparsi della divisione che influisce sulle prestazioni del programma. Quindi usa questa forma ovunque tu possa.

    È sempre meglio usare sizeof su un object reale quando ne hai uno, piuttosto che su un tipo, poiché non devi preoccuparti di fare un errore e dichiarare il tipo sbagliato.

    Ad esempio, supponiamo di avere una funzione che emette alcuni dati come stream di byte, ad esempio attraverso una rete. Chiamiamo la funzione send() , e fà assumere come argomenti un puntatore all’object da inviare e il numero di byte nell’object. Quindi, il prototipo diventa:

     void send(const void *object, size_t size); 

    E quindi è necessario inviare un numero intero, quindi lo si codifica in questo modo:

     int foo = 4711; send(&foo, sizeof (int)); 

    Ora, hai introdotto un modo sottile di spararti nel piede, specificando il tipo di foo in due punti. Se uno cambia ma l’altro no, il codice si rompe. Quindi, fallo sempre così:

     send(&foo, sizeof foo); 

    Ora sei protetto. Certo, si duplica il nome della variabile, ma questa ha un’alta probabilità di intralciare il modo in cui il compilatore può rilevare, se lo si cambia.

     int size = (&arr)[1] - arr; 

    Dai un’occhiata a questo link per spiegazioni

    È ansible utilizzare l’operatore sizeof ma non funzionerà per le funzioni perché prenderà il riferimento del puntatore che è ansible fare quanto segue per trovare la lunghezza di un array:

     len = sizeof(arr)/sizeof(arr[0]) 

    Codice originariamente trovato qui: programma C per trovare il numero di elementi in una matrice

    Se conosci il tipo di dati dell’array, puoi usare qualcosa come:

     int arr[] = {23, 12, 423, 43, 21, 43, 65, 76, 22}; int noofele = sizeof(arr)/sizeof(int); 

    O se non conosci il tipo di dati dell’array, puoi usare qualcosa come:

     noofele = sizeof(arr)/sizeof(arr[0]); 

    Nota: Questa cosa funziona solo se l’array non è definito in fase di esecuzione (come malloc) e l’array non viene passato in una funzione. In entrambi i casi, arr (nome dell’array) è un puntatore.

    La macro ARRAYELEMENTCOUNT(x) da tutti viene valutata in modo errato . Questo, realisticamente, è solo una questione delicata, perché non è ansible avere espressioni che risultino in un tipo di ‘matrice’.

     /* Compile as: CL /P "macro.c" */ # define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x[0])) ARRAYELEMENTCOUNT(p + 1); 

    In realtà valuta come:

     (sizeof (p + 1) / sizeof (p + 1[0])); 

    Mentre

     /* Compile as: CL /P "macro.c" */ # define ARRAYELEMENTCOUNT(x) (sizeof (x) / sizeof (x)[0]) ARRAYELEMENTCOUNT(p + 1); 

    Valuta correttamente a:

     (sizeof (p + 1) / sizeof (p + 1)[0]); 

    Questo in realtà non ha molto a che fare con la dimensione degli array in modo esplicito. Ho appena notato un sacco di errori dal non osservare veramente come funziona il preprocessore C. Si avvolge sempre il parametro macro, non in cui potrebbe essere coinvolta un’espressione.


    Questo è corretto; il mio esempio era cattivo. Ma questo è esattamente ciò che dovrebbe accadere. Come ho già detto p + 1 finirà come un tipo di puntatore e invaliderà l’intera macro (proprio come se si tentasse di usare la macro in una funzione con un parametro pointer).

    Alla fine della giornata, in questo particolare caso, la colpa non ha molta importanza (quindi sto solo perdendo il tempo di tutti, huzzah!), Perché non hai espressioni con un tipo di ‘array’. Ma in realtà il punto sui sottotitoli di valutazione del preprocessore credo sia importante.

    Per gli array multidimensionali è un po ‘più complicato. Spesso le persone definiscono costanti macro esplicite, es

     #define g_rgDialogRows 2 #define g_rgDialogCols 7 static char const* g_rgDialog[g_rgDialogRows][g_rgDialogCols] = { { " ", " ", " ", " 494", " 210", " Generic Sample Dialog", " " }, { " 1", " 330", " 174", " 88", " ", " OK", " " }, }; 

    Ma queste costanti possono essere valutate anche in fase di compilazione con sizeof :

     #define rows_of_array(name) \ (sizeof(name ) / sizeof(name[0][0]) / columns_of_array(name)) #define columns_of_array(name) \ (sizeof(name[0]) / sizeof(name[0][0])) static char* g_rgDialog[][7] = { /* ... */ }; assert( rows_of_array(g_rgDialog) == 2); assert(columns_of_array(g_rgDialog) == 7); 

    Si noti che questo codice funziona in C e C ++. Utilizzare gli array con più di due dimensioni

     sizeof(name[0][0][0]) sizeof(name[0][0][0][0]) 

    ecc., all’infinito.

    Dimensione di un array in C:

     int a[10]; size_t size_of_array = sizeof(a); // Size of array a int n = sizeof (a) / sizeof (a[0]); // Number of elements in array a size_t size_of_element = sizeof(a[0]); // Size of each element in array a // Size of each element = size of type 
     sizeof(array) / sizeof(array[0]) 
     #define SIZE_OF_ARRAY(_array) (sizeof(_array) / sizeof(_array[0])) 

    “hai introdotto un modo sottile di spararti al piede”

    Gli array C ‘nativi’ non memorizzano le loro dimensioni. Si consiglia quindi di salvare la lunghezza dell’array in una variabile / const separata e di passarla ogni volta che si passa la matrice, ovvero:

     #define MY_ARRAY_LENGTH 15 int myArray[MY_ARRAY_LENGTH]; 

    Dovresti sempre evitare gli array nativi (a meno che tu non possa, in tal caso, badare al tuo piede). Se stai scrivendo C ++, usa il contenitore ‘vector’ del STL . “Rispetto agli array, forniscono quasi le stesse prestazioni”, e sono molto più utili!

     // vector is a template, the  means it is a vector of ints vector numbers; // push_back() puts a new value at the end (or back) of the vector for (int i = 0; i < 10; i++) numbers.push_back(i); // Determine the size of the array cout << numbers.size(); 

    Vedi: http://www.cplusplus.com/reference/stl/vector/

    @ Magnus: lo standard definisce sizeof come risultato del numero di byte nell’object e che sizeof (char) è sempre uno. Il numero di bit in un byte è specifico per l’implementazione.

    Modifica: sezione standard ANSI C ++ 5.3.3 Sizeof:

    L’operatore sizeof fornisce il numero di byte nella rappresentazione dell’object del suo operando. […] sizeof (char), sizeof (char firmato) e sizeof (unsigned char) sono 1; il risultato di sizeof applicato a qualsiasi altro tipo fondamentale è definito dall’implementazione.

    Sezione 1.6 Il modello di memoria C ++:

    L’unità di memoria fondamentale nel modello di memoria C ++ è il byte. Un byte è almeno abbastanza grande da contenere qualsiasi membro del set di caratteri di esecuzione di base ed è composto da una sequenza contigua di bit, il cui numero è definito dall’implementazione.

    @Skizz: Sono abbastanza sicuro di aver ragione, anche se la migliore “fonte” che posso darti in questo momento è Wikipedia, dall’articolo su sizeof:

    Wikipedia è sbagliata, Skizz ha ragione. sizeof (char) è 1, per definizione.

    Voglio dire, basta leggere la voce di Wikipedia molto attentamente per vedere che è sbagliato. “multipli di char”. sizeof(char) non può mai essere diverso da “1”. Se fosse, diciamo, 2, significherebbe che sizeof(char) era due volte la dimensione del char!

    Se si vuole veramente fare questo per passare attorno al proprio array, suggerisco di implementare una struttura per memorizzare un puntatore al tipo che si desidera un array e un intero che rappresenta la dimensione dell’array. Quindi puoi passarlo alle tue funzioni. Assegna semplicemente il valore della variabile dell’array (puntatore al primo elemento) a quel puntatore. Quindi puoi andare ad Array.arr[i] per ottenere l’elemento i-esimo e usare Array.size per ottenere il numero di elementi nella matrice.

    Ho incluso del codice per te. Non è molto utile ma potresti estenderlo con più funzionalità. Ad essere sinceri però, se queste sono le cose che vuoi, dovresti smettere di usare C e usare un’altra lingua con queste funzionalità integrate.

     /* Absolutely no one should use this... By the time you're done implementing it you'll wish you just passed around an array and size to your functions */ /* This is a static implementation. You can get a dynamic implementation and cut out the array in main by using the stdlib memory allocation methods, but it will work much slower since it will store your array on the heap */ #include  #include  /* #include "MyTypeArray.h" */ /* MyTypeArray.h #ifndef MYTYPE_ARRAY #define MYTYPE_ARRAY */ typedef struct MyType { int age; char name[20]; } MyType; typedef struct MyTypeArray { int size; MyType *arr; } MyTypeArray; MyType new_MyType(int age, char *name); MyTypeArray newMyTypeArray(int size, MyType *first); /* #endif End MyTypeArray.h */ /* MyTypeArray.c */ MyType new_MyType(int age, char *name) { MyType d; d.age = age; strcpy(d.name, name); return d; } MyTypeArray new_MyTypeArray(int size, MyType *first) { MyTypeArray d; d.size = size; d.arr = first; return d; } /* End MyTypeArray.c */ void print_MyType_names(MyTypeArray d) { int i; for (i = 0; i < d.size; i++) { printf("Name: %s, Age: %d\n", d.arr[i].name, d.arr[i].age); } } int main() { /* First create an array on the stack to store our elements in. Note we could create an empty array with a size instead and set the elements later. */ MyType arr[] = {new_MyType(10, "Sam"), new_MyType(3, "Baxter")}; /* Now create a "MyTypeArray" which will use the array we just created internally. Really it will just store the value of the pointer "arr". Here we are manually setting the size. You can use the sizeof trick here instead if you're sure it will work with your compiler. */ MyTypeArray array = new_MyTypeArray(2, arr); /* MyTypeArray array = new_MyTypeArray(sizeof(arr)/sizeof(arr[0]), arr); */ print_MyType_names(array); return 0; } 

    Il modo migliore è salvare queste informazioni, ad esempio, in una struttura:

     typedef struct { int *array; int elements; } list_s; 

    Implementa tutte le funzioni necessarie come creare, distruggere, controllare l’uguaglianza e tutto il resto necessario. È più facile passare come parametro.

    Puoi usare l’operatore & . Ecco il codice sorgente:

     #include #include int main(){ int a[10]; int *p; printf("%p\n", (void *)a); printf("%p\n", (void *)(&a+1)); printf("---- diff----\n"); printf("%zu\n", sizeof(a[0])); printf("The size of array a is %zu\n", ((char *)(&a+1)-(char *)a)/(sizeof(a[0]))); return 0; }; 

    Ecco l’output del campione

     1549216672 1549216712 ---- diff---- 4 The size of array a is 10 

    La funzione sizeof restituisce il numero di byte che viene utilizzato dall’array nella memoria. Se si desidera calcolare il numero di elementi nell’array, è necessario dividerlo con la dimensione del tipo di variabile dell’array. Diciamo int array[10]; , se il numero intero di tipo variabile nel tuo computer è a 32 bit (o 4 byte), per ottenere la dimensione dell’array, devi fare quanto segue:

     int array[10]; int sizeOfArray = sizeof(array)/sizeof(int); 
     int a[10]; int size = (*(&a+1)-a) ; 

    per maggiori dettagli: https://aticleworld.com/how-to-find-sizeof-array-in-cc-without-using-sizeof/ https://www.geeksforgeeks.org/how-to-find-size- di-array-in-cc-senza-using-sizeof operatore /

    Uso:

     int a=[10] = {1, 2, 3, 4, 5}; int n = sizeof(a); printf("%d", n); 

    Produzione:

     5 

    Motivo: calcola il numero di elementi contenuti nell’array anziché il numero di spazi liberi ad esso assegnati.