Pourquoi la taille d’un paramètre de tableau n’est-elle pas la même que celle de main?

Pourquoi la taille d’un tableau n’est-elle pas envoyée comme paramètre au sein de main?

#include  void PrintSize(int p_someArray[10]); int main () { int myArray[10]; printf("%d\n", sizeof(myArray)); /* As expected, 40 */ PrintSize(myArray);/* Prints 4, not 40 */ } void PrintSize(int p_someArray[10]){ printf("%d\n", sizeof(p_someArray)); } 

Non , le type de tableau est implicitement converti en type de pointeur lorsque vous le transmettez à une fonction.

Alors,

 void PrintSize(int p_someArray[10]) { printf("%zu\n", sizeof(p_someArray)); } 

et

 void PrintSize(int *p_someArray) { printf("%zu\n", sizeof(p_someArray)); } 

sont équivalents. Donc, vous obtenez la valeur de sizeof(int*)

C’est un pointeur, c’est pourquoi c’est une implémentation courante de passer la taille du tableau en second paramètre à la fonction

Comme d’autres l’ont indiqué, les tableaux se désintègrent en pointeurs vers leur premier élément lorsqu’ils sont utilisés comme parameters de fonction. Il convient également de noter que sizeof n’évalue pas l’expression et ne nécessite pas de parenthèses lorsqu’il est utilisé avec une expression. Votre paramètre n’est donc pas utilisé du tout, vous pouvez donc écrire la taille avec le type plutôt que la valeur.

 #include  void PrintSize1 ( int someArray[][10] ); void PrintSize2 ( int someArray[10] ); int main () { int myArray[10]; printf ( "%d\n", sizeof myArray ); /* as expected 40 */ printf ( "%d\n", sizeof ( int[10] ) ); /* requires parens */ PrintSize1 ( 0 ); /* prints 40, does not evaluate 0[0] */ PrintSize2 ( 0 ); /* prints 40, someArray unused */ } void PrintSize1 ( int someArray[][10] ) { printf ( "%d\n", sizeof someArray[0] ); } void PrintSize2 ( int someArray[10] ) { printf ( "%d\n", sizeof ( int[10] ) ); } 

Vous devrez donc passer la longueur du tableau en second paramètre. Lorsque vous écrivez du code, dans lequel vous déclarez à la fois un tableau de taille constante et que vous transmettez ce tableau à une fonction, il est pénible que la constante de longueur du tableau apparaisse à plusieurs endroits dans votre code …

K & R à la rescousse:

 #define N_ELEMENTS(array) (sizeof(array)/sizeof((array)[0])) 

Alors maintenant vous pouvez faire par exemple:

 int a[10]; ... myfunction(a, N_ELEMENTS(a)); 

Parce que les tableaux se dégradent en pointeurs lorsqu’ils sont passés en parameters. C’est comme ça que C fonctionne, même si vous pouvez passer des “tableaux” en C ++ par référence et surmonter ce problème. Notez que vous pouvez passer des tableaux de tailles différentes à cette fonction:

  // 10 is superfluous here! You can pass an array of different size! void PrintSize(int p_someArray[10]); 

Dans c ++, vous pouvez passer un tableau par référence à cet effet:

 void foo(int (&array)[10]) { std::cout << sizeof(array) << "\n"; } 

Le comportement que vous avez trouvé est en fait une grosse verrue en langage C. Chaque fois que vous déclarez une fonction qui prend un paramètre de tableau, le compilateur vous ignore et change le paramètre en un pointeur. Donc, ces déclarations se comportent toutes comme la première:

 void func(int *a) void func(int a[]) void func(int a typedef int array_plz[5]; void func(array_plz a) 

a sera un pointeur sur int dans les quatre cas. Si vous passez un tableau à func, il se transformera immédiatement en un pointeur vers son premier élément. (Sur un système 64 bits, un pointeur 64 bits est deux fois plus grand qu’un int 32 bits, donc votre ratio sizeof renvoie 2.)

Le seul objective de cette règle est de maintenir la compatibilité ascendante avec les compilateurs historiques qui ne prenaient pas en charge les valeurs d’agrégat de passage en tant qu’arguments de fonction.

Cela ne signifie pas qu’il est impossible de passer un tableau à une fonction. Vous pouvez contourner cette verrue en incorporant le tableau dans une structure (il s’agit essentiellement de la fonction std :: array de C ++ 11):

 struct array_rly { int a[5]; }; void func(struct array_rly a) { printf("%zd\n", sizeof(aa)/sizeof(aa[0])); /* prints 5 */ } 

ou en passant un pointeur sur le tableau:

 void func(const int (*a)[5]) { printf("%zd\n", sizeof(*a)/sizeof((*a)[0])); /* prints 5 */ } 

Si la taille du tableau n’est pas une constante à la compilation, vous pouvez utiliser la technique du pointeur vers le tableau avec les tableaux de longueur variable C99:

 void func(int n, const int (*a)[n]) { printf("%zd\n", sizeof(*a)/sizeof((*a)[0])); /* prints n */ } 

En langage C, il n’y a pas de méthode pour déterminer la taille d’un tableau inconnu, il faut donc transmettre la quantité ainsi qu’un pointeur vers le premier élément.

Vous ne pouvez pas passer de tableaux à des fonctions.

Si vous vouliez vraiment imprimer la taille, vous pourriez passer un pointeur à un tableau, mais ce ne serait pas du tout générique car vous devez également définir la taille du tableau pour la fonction.

 #include  void PrintSize(int (*p_anArray)[10]); int main(void) { int myArray[10]; printf("%d\n", sizeof(myArray)); /* as expected 40 */ PrintSize(&myArray);/* prints 40 */ } void PrintSize(int (*p_anArray)[10]){ printf("%d\n", (int) sizeof(*p_anArray)); } 

Le comportement est par conception.

La même syntaxe dans la déclaration de paramètre de fonction signifie une chose complètement différente que dans la définition de variable locale.

La raison est décrite dans d’autres réponses.

En langage C, lorsque vous transmettez le tableau en tant qu’argument à la fonction, il est automatiquement converti en pointeur, le passage d’un tableau à une autre fonction est connu sous le nom d’appel par référence. C’est la raison pour laquelle la fonction appelée ne reçoit que le pointeur qui pointe vers le premier élément de la fonction.

fun (int a []) est similaire à fun (int * a);

Ainsi, lorsque vous imprimez la taille du tableau, il affiche la taille du premier élément.

Dans ‘C’, la langue de programmation ‘sizeof ()’ est l’opérateur et il retourne la taille de l’object en octets. L’argument de l’opérateur ‘sizeof ()’ doit être un type de valeur gauche (entier, nombre flottant, struct, tableau ) .Si vous voulez connaître la taille d’un tableau en octets, vous pouvez le faire très simplement. Utilisez juste l’opérateur ‘sizeof ()’ et pour son argument utilisez le nom du tableau. Par exemple:

 #include  main(){ int n[10]; printf("Size of n is: %d \n", sizeof(n)); } 

La sortie sur le système 32 bits sera la suivante: la taille de n est la suivante: 40 car ineteger sur le système 32 est de 4 octets. Sur 64 x, il est de 8 octets. Dans ce cas, nous avons 10 entiers déclarés dans un tableau. int) ‘.

Quelques conseils:

Si nous avons un tableau déclaré comme celui-ci, ‘int n [] = {1, 2, 3, … 155 ..};’. Nous voulons donc savoir combien d’éléments sont stockés dans ce tableau. Utilisez cet alghorithme:

sizeof (name_of_the_array) / sizeof (array_type)

Code: #include

principale(){

 int n[] = { 1, 2, 3, 44, 6, 7 }; printf("Number of elements: %d \n", sizeof(n) / sizeof(int)); return 0; 

}

Les tableaux ne sont que de taille lâche. Pour la plupart, un tableau est un pointeur sur la mémoire. La taille dans votre déclaration indique seulement au compilateur la quantité de mémoire à allouer pour le tableau – elle n’est pas associée au type, donc sizeof () n’a rien à faire.