📊 Le cours : ranger plusieurs valeurs
Un tableau range plusieurs valeurs du même type sous un seul nom. C'est la structure de données de base du C. Contrairement à une liste Python, sa taille est fixée à la création et ne change plus. Les notions générales (indices, parcours, copies) sont celles du chapitre Tableaux 1D.
Déclarer et initialiser
Si on donne moins de valeurs que de cases, les cases restantes sont mises à 0. Si on ne donne rien, un tableau local contient des valeurs quelconques : initialise-le.
#include <stdio.h>
int main(void) {
int a[5] = {1, 2}; /* 1 2 0 0 0 */
int b[] = {7, 8, 9}; /* taille déduite : 3 cases */
int c[4] = {0}; /* quatre zéros */
for (int i = 0; i < 5; i++) {
printf("%d ", a[i]);
}
printf("\n");
printf("b a %d cases\n", (int) (sizeof(b) / sizeof(b[0])));
printf("c[3] = %d\n", c[3]);
return 0;
}
Affichage1 2 0 0 0
b a 3 cases
c[3] = 0
La taille d'un tableau est une constante connue à la compilation. Pour une taille connue seulement à l'exécution, on utilise la mémoire dynamique (voir Mémoire dynamique).
Accéder aux éléments
t[i] désigne la case d'indice i, qu'on peut lire ou modifier. Les cases sont côte à côte en mémoire, ce qui rend l'accès à n'importe quelle case immédiat.
indice : 0 1 2 3
+------+------+------+------+
notes | 12 | 15 | 9 | 18 |
+------+------+------+------+
Aucune vérification des bornes
Python lève une IndexError si l'indice est trop grand. Le C, lui, lit ou écrit simplement la mémoire voisine : t[5] dans un tableau de 5 cases est un comportement indéfini (résultat faux, plantage, ou « ça marche » par hasard).
Parcourir un tableau
Le parcours classique utilise un for avec i < n. Voici la recherche de l'indice du maximum : on garde l'indice du meilleur candidat et on le met à jour quand on trouve plus grand.
#include <stdio.h>
int main(void) {
int t[] = {3, 9, 2, 7};
int n = sizeof(t) / sizeof(t[0]);
int imax = 0;
for (int i = 1; i < n; i++) {
if (t[i] > t[imax]) {
imax = i;
}
}
printf("max = %d a l'indice %d\n", t[imax], imax);
return 0;
}
Affichagemax = 9 a l'indice 1
Tableaux et fonctions
Quand on passe un tableau à une fonction, il n'est pas copié : la fonction reçoit l'adresse de la première case. Elle peut donc le modifier, mais elle ne connaît plus sa taille : on la passe en second paramètre. Ajoute const si la fonction ne doit pas modifier le contenu.
#include <stdio.h>
int somme(const int t[], int n) {
int s = 0;
for (int i = 0; i < n; i++) {
s += t[i];
}
return s;
}
void doubler(int t[], int n) {
for (int i = 0; i < n; i++) {
t[i] *= 2; /* modifie le tableau de l'appelant */
}
}
int main(void) {
int t[] = {1, 2, 3, 4};
doubler(t, 4);
printf("%d\n", somme(t, 4));
return 0;
}
Ce comportement s'explique par les pointeurs : le nom d'un tableau se transforme en adresse de sa première case (voir Pointeurs).
Tableaux à deux dimensions
int g[L][C] est un tableau de L lignes de C cases. Les lignes sont rangées les unes derrière les autres en mémoire. On parcourt avec deux boucles imbriquées (voir l'exemple de la deuxième carte) ; le coût est proportionnel à L × C, comme pour les matrices du chapitre Tableaux 2D.
Copier un tableau
On ne peut pas écrire b = a pour deux tableaux. Il faut copier case par case, ou utiliser memcpy de <string.h>. (En Python, b = a crée un alias ; en C, c'est tout simplement refusé. Voir Aliasing et copies.)
#include <stdio.h>
#include <string.h>
int main(void) {
int a[3] = {1, 2, 3};
int b[3];
memcpy(b, a, sizeof a); /* copie les 3 entiers */
b[0] = 99;
printf("%d %d\n", a[0], b[0]);
return 0;
}