next up previous contents index
Next: Fonctions sur les chaînes Up: No Title Previous: Chaînes de caractères

Tableaux et passage par référence

      

Pour définir une fonction dont un argument est un tableau, il est inutile de préciser sa taille dans le paramètre correspondant (même si cette taille est spécifiée, elle n'est pas utilisée par le corps de la fonction). Ainsi,

double f(double t[100]) { ... }

a exactement la même signification que

double f(double t[]) { ... }

Il est généralement nécessaire de spécifier séparément la taille de l'objet qui sera passé en argument, car elle devra souvent être utilisée :

double f(int m, double t[]) {
  int i;

  for (i=0; i<m; i++) { ... }
}

On appellera f(2,t) si l'on sait que t est un tableau de taille (au moins) 2. Le corps de f pourra ainsi utiliser la valeur m de m pour accéder aux t[i] pour $0\le i\le m-1$. Notons que la définition

double f_illegal(int m, double t[m]) { ... }

n'est pas permise : la taille du tableau, si elle est spécifiée entre les crochets, doit être une constante.

Cette taille n'est en général pas spécifiée en argument dans les cas où l'on sait que l'on travaille toujours avec des tableaux de même dimension, cette dimension étant indiquée littéralement dans le corps de f, par exemple pour des tableaux de taille 2 :

  for(i=0; i<2; i++) { ... }

Un autre cas où il n'est pas nécessaire de spécifier la dimension est celui des chaînes de caractères (car la fin d'une chaîne est signalée par un élément spécial).

On indique parfois par deux paramètres la tranche des indices sur lesquels la fonction va opérer :

double f(int m, int n, double t[]) { 
  int i;

  for (i=m; i<=n; i++) { ... }
  ...
}

 

Le tableau argument est passé par valeur, comme tout autre argument ; or, la valeur d'un tableau est l'adresse du bloc de mémoire alloué ; c'est donc cette adresse qui sert à initialiser le paramètre correspondant, lors de l'invocation de la fonction. Comme seule l'adresse du tableau, et non son contenu, est copiée lors de l'invocation de la fonction, celle-ci opère sur le tableau lui-même, et non sur une copie (ce qui serait d'ailleurs une cause d'inefficacité) : le tableau est passé par valeur, mais ses éléments sont passés par référence.

On peut calculer la somme des éléments d'un tableaux d'entiers avec la fonction :

  int array_sum(int n, int t[]) {
    return n>0 ? t[n-1] + array_sum(n-1, t) : 0;
}

Bien qu'il s'agisse d'une fonction récursive, le bloc d'activation de chaque invocation ne comportera que l'adresse du tableau (qui ne varie d'ailleurs pas).

Si le tableau passé en argument n'est pas modifié par la fonction, il est bon de spécifier ce paramètre comme une constante :

 

  int array_sum(int n, const int t[]);

On peut profiter de ce passage par référence pour faire modifier la valeur d'un élément du tableau par la fonction. Par exemple, on échange la valeur de deux éléments d'un tableau par :

 

void array_swap(double t[], int m, int n) {
  double temp = t[m] ;

  t[m] = t[n] ;
  t[n] = temp;
}

int main () {
  double t[] = {1,2,3,4,5,6};
  array_swap(t, 2, 4);
  ...
}

 

Comme C ne permet pas de retourner un tableau, on utilise généralement le passage par référence des éléments d'un tableau pour y écrire le résultat de la fonction (une autre méthode sera l'allocation dynamique). On définira l'addition de deux vecteurs (des tableaux de taille 3) par une fonction

void vecteur_add(const double[], const double[], double[]);

dont les deux premiers paramètres sont les vecteurs à additionner (ils sont spécifiés const car ils ne seront pas modifiés), et le troisième paramètre est le résultat de l'addition. On l'appellera ainsi :

  double x[] = {1.0, 2.0, 3.0};
  double y[] = {4.0, 5.0, 6.0};
  double z[3] ;
  vecteur_add(x,y,z);

next up previous contents index
Next: Fonctions sur les chaînes Up: No Title Previous: Chaînes de caractères
Jean-Philippe Chancelier
9/29/1998