next up previous contents index
suivant: Tableaux de taille inconnue monter: main précédent: Chaînes de caractères   Table des matières   Index


Tableaux et passage par adresse

Tout tableau peut être argument d'une fonction. Le paramètre correspondant doit être déclaré de type tableau. Cependant, il est inutile de préciser sa taille ; même si cette taille est spécifiée, elle n'est pas utilisée par le corps de la fonction. Ainsi, les deux définitions suivantes ont exactement la même signification :


double f(double t[100]) { ... }
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$. 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++) { ... }
  ...
}

Notons que la définition suivante n'est pas permise : la taille du tableau, si elle est spécifiée entre les crochets, par souci de documentation du programme, doit être une constante, et non un paramètre.


double f_ERREUR(int m, double t[m]) { ... }  // ERREUR


Le tableau argument est passé par valeur ; 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 adresse.

On peut profiter de ce passage par adresse 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);
  ...
}

Si le tableau passé en argument n'est pas modifié par la fonction, il est recommandé de spécifier ce paramètre comme une constante. Par exemple, on peut calculer la somme des éléments d'un tableaux d'entiers avec la fonction :


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

On remarquera que 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 d'un appel à l'autre).


Signalons le cas spécial des chaînes de caractères de C. Si une chaîne, représentée par un tableau de caractères, doit être passée en argument à une fonction, le paramètre correspondant doit être de type char []. Contrairement à des tableaux quelconques, il n'est pas nécessaire de passer en argument le nombre d'éléments de la chaîne, à cause du '\0' final. Par exemple, la fonction suivante permet de copier une chaîne dans une autre.


void strcopy(char to[], const char from[]) {
  int i = 0;

  do {
    to[i] = from[i];
    i = i+1;
  } 
  while (from[i-1] != '\0');
}

Quand cette fonction est invoquée, son premier argument doit avoir été défini comme un tableau de caractères de taille strictement supérieure à la longueur de la chaîne constituant son deuxième argument.

Comme C++ ne permet pas de retourner un tableau, on utilise généralement le passage par adresse 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 $n$) par une fonction


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

dont les deux premiers paramètres tableaux sont les vecteurs à additionner (ils sont spécifiés const car ils ne seront pas modifiés), et le dernier 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(3, x, y, z);


next up previous contents index
suivant: Tableaux de taille inconnue monter: main précédent: Chaînes de caractères   Table des matières   Index
R Lalement