104 votes

Différence entre tableau de passage et pointeur de tableau en fonction en C

Quelle est la différence entre les deux fonctions en C?

 void f1(double a[]) {
   //...
}

void f2(double *a) {
   //...
}
 

Si je devais appeler les fonctions sur un tableau sensiblement long, ces deux fonctions se comporteraient-elles différemment, prendraient-elles plus d'espace sur la pile?

110voto

John Bode Points 33046

Tout d'abord, certains standardese:

6.7.5.3 Fonction declarators (y compris les prototypes)
...
7 de la déclaration d'Un paramètre comme ‘tableau de type" doit être réglé à ‘qualifié pointeur vers tapez", où le type de qualificatifs (le cas échéant) sont celles spécifiées dans l' [ et ] de la type de tableau de dérivation. Si le mot-clé static apparaît également au sein de l' [ et ] de la type de tableau de dérivation, puis pour chaque appel à la fonction, la valeur du correspondant argument réel doit fournir l'accès au premier élément d'un tableau avec au moins autant d' éléments, comme spécifié par la taille de l'expression.

Donc, en bref, tout paramètre de la fonction déclarée T a[] ou T a[N] est traitée comme si elle était déclarée T *a.

Alors, pourquoi sont les paramètres de tableau traitées comme si elles avaient été déclarées comme des pointeurs? Voici pourquoi:

6.3.2.1 Lvalues, les tableaux et les pointeurs de fonction
...
3 Sauf quand c'est l'opérande de l' sizeof de l'opérateur ou de l'unaire & de l'opérateur ou d'un un littéral de chaîne utilisée pour initialiser un tableau, une expression qui a le type ‘tableau de type" est converti à une expression de type ‘pointeur de type" qui pointe vers le premier élément de l'objet tableau et n'est pas une lvalue. Si le tableau d'objet a s'inscrire en classe de stockage, le le comportement est indéfini.

Étant donné le code suivant:

int main(void)
{
  int arr[10];
  foo(arr);
  ...
}

Dans l'appel d' foo, le tableau de l'expression arr n'est pas un opérande de sizeof ou &, de sorte que son type est implicitement converti à partir du "tableau de 10 éléments d' int" à "pointeur int", selon 6.2.3.1/3. Ainsi, foo recevrez une valeur de type pointeur, plutôt qu'un tableau de valeur.

En raison de 6.7.5.3/7, vous pouvez écrire foo comme

void foo(int a[]) // or int a[10]
{
  ...
}

mais cela sera interprété comme une

void foo(int *a)
{
  ...
}

Ainsi, les deux formes sont identiques.

La dernière phrase 6.7.5.3/7 a été introduit avec le C99, et signifie que si vous avez une déclaration de paramètre comme

void foo(int a[static 10])
{
  ...
}

le paramètre effectif correspondant à l' a doit être un tableau avec au moins 10 éléments.

28voto

Thomas Pornin Points 36984

La différence est purement syntaxique. En C, lorsque la notation de tableau est utilisée pour un paramètre de fonction, il est automatiquement transformé en une déclaration de pointeur.

0voto

mcaaltuntas Points 2573

Non, il n'y a pas de différence entre eux. Pour tester j'ai écrit ce code C dans le compilateur Dev C ++ (mingw)

 #include <stdio.h>

void function(int* array) {
     int a =5;
}

void main() {  
  int array[]={2,4};
  function(array);
  getch();
}
 

Lorsque je désassemble la fonction principale dans le fichier .exe des deux versions du fichier binaire appelant dans IDA, je reçois exactement le même code d'assemblage, comme ci-dessous.

 push    ebp
mov     ebp, esp
sub     esp, 18h
and     esp, 0FFFFFFF0h
mov     eax, 0
add     eax, 0Fh
add     eax, 0Fh
shr     eax, 4
shl     eax, 4
mov     [ebp+var_C], eax
mov     eax, [ebp+var_C]
call    sub_401730
call    sub_4013D0
mov     [ebp+var_8], 2
mov     [ebp+var_4], 4
lea     eax, [ebp+var_8]
mov     [esp+18h+var_18], eax
call    sub_401290
call    _getch
leave
retn
 

Donc, il n'y a pas de différence entre les deux versions de cet appel. Au moins, le compilateur les menace également.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X