Le programme C suivant:
int doStuff(int afm[]); int main(){ int afm1[9] = {1,2,3,4,5,6,7,8,9}; //size=9 int afmLength = sizeof(afm1)/sizeof(int); printf("main: Length Of Array=%d\n", afmLength); //9 OK int k = doStuff(afm1); system("PAUSE"); return 0; } int doStuff(int afm[]){ int afmLength = sizeof(afm)/sizeof(int); printf("doStuff: Length Of Array=%d\n", afmLength); //1 WRONG return 1; }
produit la sortie suivante:
main: Length Of Array=9 doStuff: Length Of Array=1
Pourquoi la taille du tableau est-elle calculée correctement dans main, mais erronée dans la fonction?
Parce que, en main
vous avez un tableau et que dans la fonction, vous avez un pointeur sur ce tableau.
int doStuff(int afm[])
est équivalent à
int doStuff(int *afm)
En ajoutant à la réponse de David Heffernan (qui est correcte), vous devriez avoir un autre paramètre qui serait la longueur du tableau passé à votre méthode doStuff
.
De la norme de langage C (projet n1256 ):
6.3.2.1 Lvalues, tableaux et désignateurs de fonctions
…
3 Sauf s’il s’agit de l’opérande de l’opérateursizeof
ou de l’opérateur unaire&
, ou s’il s’agit d’un littéral utilisé pour initialiser un tableau, une expression de type ” tableau de type ” est convertie en une expression de type ” pointeur taper ” qui pointe vers l’élément initial de l’object tableau et n’est pas une lvalue. Si l’object tableau a une classe de stockage de registre, le comportement n’est pas défini.
Mémorisez ce paragraphe, car l’une des plus grandes sources de brûlures d’estomac dans la programmation en C est la façon dont C traite les expressions de tableau.
Lorsque vous appelez doStuff(afm1);
, l’expression afm1
est convertie implicitement du type “tableau à 9 éléments d’ int
” en “pointeur sur int
“, et la valeur de l’expression est identique à celle de &afm1[0]
. Donc, ce que doStuff
reçoit est une valeur de pointeur, pas un tableau.
Dans le contexte d’une déclaration de paramètre de fonction, T a[]
et T a[N]
sont tous deux interprétés comme T *a
:
6.7.5.3 Déclarateurs de fonctions (y compris les prototypes)
…
7 La déclaration d’un paramètre sous la forme ” tableau de type ” doit être réglée sur ” pointeur qualifié vers type ”, les qualificateurs de type (le cas échéant) étant ceux spécifiés dans les[
et]
de la dérivation de type de tableau. Si le mot cléstatic
apparaît également dans le[
et]
de la dérivation du type de tableau, alors, pour chaque appel à la fonction, la valeur de l’argument réel correspondant doit permettre d’accéder au premier élément d’un tableau avec au moins autant d’éléments que ceux spécifiés. par l’expression de taille.
Étant donné que doStuff
reçoit une valeur de pointeur et non un tableau, l’astuce de sizeof
ne fonctionne pas. En général, vous devez indiquer explicitement à une fonction la taille d’un tableau que vous lui transmettez; vous ne pouvez pas déterminer cela à partir de la valeur du pointeur lui-même.
Ainsi, lorsque vous appelez doStuff
depuis main
, vous devez faire quelque chose comme:
doStuff(afm1, sizeof afm1/sizeof *afm1); ... int doStuff(int *afm, size_t afmsize) { ... }