Comment déterminer la taille de mon tableau en C?

Comment déterminer la taille de mon tableau en C?

C’est-à-dire le nombre d’éléments que le tableau peut contenir?

Résumé:

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

Pour déterminer la taille de votre tableau en octets, vous pouvez utiliser l’opérateur sizeof :

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

Sur mon ordinateur, la taille est de 4 octets, n est donc de 68.

Pour déterminer le nombre d’éléments dans le tableau, nous pouvons diviser la taille totale du tableau par la taille de l’élément de tableau. Vous pouvez le faire avec le type, comme ceci:

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

et obtenez la bonne réponse (68/4 = 17), mais si vous changiez de type, vous auriez un bug si vous avez oublié de changer la sizeof(int) .

Ainsi, le diviseur préféré est sizeof(a[0]) , la taille de l’élément zeroeth du tableau.

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

Un autre avantage est que vous pouvez désormais facilement paramétrer le nom du tableau dans une macro et obtenir:

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

La sizeof manière est la bonne façon si vous ne traitez pas de tableaux non reçus en parameters. Un tableau envoyé en tant que paramètre à une fonction est traité comme un pointeur, de sorte que sizeof renvoie la taille du pointeur, au lieu du tableau.

Ainsi, à l’intérieur des fonctions, cette méthode ne fonctionne pas. Au lieu de cela, transmettez toujours un paramètre supplémentaire size_t size indiquant le nombre d’éléments dans le tableau.

Tester:

 #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]) )); } 

Sortie (dans un système d’exploitation Linux 64 bits):

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

Sortie (dans un OS Windows 32 bits):

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

Il est important de noter que sizeof ne permet pas de traiter une valeur de tableau qui a décru en un pointeur: même si elle pointe vers le début d’un tableau, le compilateur est identique à un élément unique de ce tableau. tableau. Un pointeur ne “mémorise” rien d’autre concernant le tableau utilisé pour l’initialiser.

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

La taille du “truc” est la meilleure façon que je connaisse, avec un petit changement important (pour moi, une grande bête noire) dans l’utilisation de la parenthèse.

Comme le montre l’entrée Wikipedia, la sizeof de C n’est pas une fonction; c’est un opérateur . Ainsi, il ne nécessite pas de parenthèse autour de son argument, sauf si l’argument est un nom de type. C’est facile à retenir, car l’argument ressemble à une expression de dissortingbution, qui utilise également des parenthèses.

Donc: Si vous avez ce qui suit:

 int myArray[10]; 

Vous pouvez trouver le nombre d’éléments avec un code comme celui-ci:

 size_t n = sizeof myArray / sizeof *myArray; 

Cela me semble beaucoup plus facile que l’alternative avec des parenthèses. Je privilégie également l’utilisation de l’astérisque dans la partie droite de la division, car elle est plus concise que l’indexation.

Bien sûr, tout cela est compilé, il n’y a donc pas lieu de s’inquiéter de la division qui affecte les performances du programme. Alors, utilisez ce formulaire partout où vous le pouvez.

Il est toujours préférable d’utiliser sizeof sur un object réel lorsque vous en avez un, plutôt que sur un type, car vous n’avez pas à vous soucier de faire une erreur et d’indiquer le type incorrect.

Par exemple, supposons que vous ayez une fonction qui émet des données sous forme de stream d’octets, par exemple sur un réseau. Appelons la fonction send() et lui faisons prendre comme arguments un pointeur sur l’object à envoyer et le nombre d’octets dans l’object. Donc, le prototype devient:

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

Et puis vous devez envoyer un nombre entier, donc vous le codez comme ceci:

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

Maintenant, vous avez introduit une manière subtile de vous tirer dans le pied, en spécifiant le type de foo à deux endroits. Si l’un change mais que l’autre ne le fait pas, le code casse. Ainsi, faites-le toujours comme ceci:

 send(&foo, sizeof foo); 

Maintenant, vous êtes protégé. Bien sûr, vous dupliquez le nom de la variable, mais il est fort probable que le compilateur le détecte, si vous le modifiez.

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

Consultez ce lien pour des explications

Vous pouvez utiliser l’opérateur sizeof mais cela ne fonctionnera pas pour les fonctions car il faudra la référence du pointeur que vous pouvez faire pour trouver la longueur d’un tableau:

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

Code trouvé à l’origine ici: C programme pour trouver le nombre d’éléments dans un tableau

Si vous connaissez le type de données du tableau, vous pouvez utiliser quelque chose comme:

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

Ou si vous ne connaissez pas le type de données du tableau, vous pouvez utiliser quelque chose comme:

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

Remarque: Cette chose ne fonctionne que si le tableau n’est pas défini au moment de l’exécution (comme malloc) et que le tableau n’est pas transmis dans une fonction. Dans les deux cas, arr (nom du tableau) est un pointeur.

La macro ARRAYELEMENTCOUNT(x) utilisée par tout le monde est mal évaluée. Ceci, de manière réaliste, est juste une question sensible, car vous ne pouvez pas avoir des expressions qui génèrent un type “tableau”.

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

Évalue en fait comme:

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

Tandis que

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

Il évalue correctement à:

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

Cela n’a vraiment rien à voir avec la taille des tableaux explicitement. J’ai juste remarqué beaucoup d’erreurs de ne pas vraiment observer le fonctionnement du préprocesseur C. Vous enroulez toujours le paramètre macro, pas une expression dans peut être impliqué dans.


C’est correct; mon exemple était mauvais. Mais c’est exactement ce qui devrait arriver. Comme je l’ai mentionné précédemment, p + 1 se retrouvera comme un type de pointeur et invalidera la macro entière (comme si vous aviez essayé d’utiliser la macro dans une fonction avec un paramètre de pointeur).

En fin de compte, dans ce cas particulier , la faute n’a pas vraiment d’importance (donc je perds tout le temps, huzzah!), Parce que vous n’avez pas d’expressions avec un type de «tableau». Mais je pense que l’important réside dans les subtilités de l’évaluation du préprocesseur.

Pour les tableaux multidimensionnels, c’est un peu plus compliqué. Souvent, les gens définissent des macro constantes explicites, c.-à-d.

 #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", " " }, }; 

Mais ces constantes peuvent aussi être évaluées à la compilation avec 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); 

Notez que ce code fonctionne en C et C ++. Pour les tableaux avec plus de deux dimensions, utilisez

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

etc., à l’infini.

Taille d’un tableau en 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])) 

“Vous avez introduit une manière subtile de vous tirer dans le pied”

Les baies «natives» ne stockent pas leur taille. Il est donc recommandé de sauvegarder la longueur du tableau dans une variable distincte / const et de la transmettre chaque fois que vous passez le tableau, à savoir:

 #define MY_ARRAY_LENGTH 15 int myArray[MY_ARRAY_LENGTH]; 

Vous devez toujours éviter les tableaux natifs (sauf si vous ne pouvez pas, dans ce cas, ne vous occupez pas de votre pied). Si vous écrivez en C ++, utilisez le conteneur ‘vector’ de la STL . “Comparés aux tableaux, ils offrent presque les mêmes performances”, et ils sont beaucoup plus utiles!

 // 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(); 

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

@ Magnus: la norme définit sizeof comme donnant le nombre d’octets dans l’object et que sizeof (char) est toujours un. Le nombre de bits dans un octet est spécifique à l’implémentation.

Modifier: ANSI C ++ standard section 5.3.3 Sizeof:

L’opérateur sizeof donne le nombre d’octets dans la représentation d’object de son opérande. […] sizeof (char), sizeof (char signé) et sizeof (unsigned char) sont 1; le résultat de sizeof appliqué à tout autre type fondamental est défini par l’implémentation.

Section 1.6 Le modèle de mémoire C ++:

L’unité de stockage fondamentale du modèle de mémoire C ++ est l’octet. Un octet est au moins assez grand pour contenir n’importe quel membre du jeu de caractères d’exécution de base et est composé d’une séquence contiguë de bits, dont le nombre est défini par la mise en œuvre.

@ Skizz: Je suis presque sûr d’avoir raison, bien que la meilleure “source” que je puisse vous donner pour le moment est Wikipedia, à partir de l’article sur sizeof:

Wikipedia a tort, Skizz a raison. sizeof (char) est 1, par définition.

Je veux dire, il suffit de lire très attentivement l’entrée de Wikipedia pour voir que c’est faux. “multiples de char”. sizeof(char) ne peut jamais être autre chose que “1”. Si c’était le cas, disons 2, cela signifierait que sizeof(char) était deux fois la taille de char!

Si vous voulez vraiment faire cela pour faire circuler votre tableau, je suggère d’implémenter une structure pour stocker un pointeur sur le type de tableau souhaité et un entier représentant la taille du tableau. Ensuite, vous pouvez le transmettre à vos fonctions. Atsortingbuez simplement la valeur de la variable de tableau (pointeur sur le premier élément) à ce pointeur. Ensuite, vous pouvez aller à Array.arr[i] pour obtenir le i-ème élément et utiliser Array.size pour obtenir le nombre d’éléments dans le tableau.

J’ai inclus du code pour vous. Ce n’est pas très utile, mais vous pouvez l’étendre avec plus de fonctionnalités. Pour être honnête, si ce sont les choses que vous voulez, vous devriez cesser d’utiliser C et utiliser un autre langage avec ces fonctionnalités intégrées.

 /* 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; } 

Le meilleur moyen est de sauvegarder ces informations, par exemple dans une structure:

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

Implémentez toutes les fonctions nécessaires telles que créer, détruire, vérifier l’égalité et tout ce dont vous avez besoin. Il est plus facile de passer en paramètre.

Vous pouvez utiliser l’opérateur & . Voici le code source:

 #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; }; 

Voici la sortie de l’échantillon

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

La fonction sizeof renvoie le nombre d’octets utilisés par votre tableau dans la mémoire. Si vous voulez calculer le nombre d’éléments dans votre tableau, vous devez diviser ce nombre par le type de variable sizeof du tableau. Disons int array[10]; , si le type entier de variable dans votre ordinateur est de 32 bits (ou 4 octets), pour obtenir la taille de votre tableau, procédez comme suit:

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

pour plus de détails: https://aticleworld.com/how-to-find-sizeof-array-in-cc-without-using-sizeof/ https://www.geeksforgeeks.org/how-to-find-size- of-array-in-cc-sans-using-sizeof-operator /

Utilisation:

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

Sortie:

 5 

Raison: calcule le nombre d’éléments contenus dans le tableau plutôt que le nombre d’espaces libres qui lui sont alloués.