Ce guide présente les principales approches d'initialisation à zéro d'une matrice en C, avec des exemples concrets et une discussion sur les cas d'usage appropriés.
- Initialiseur avec une seule valeur
La forme la plus compacte consiste à fournir le premier élément dans une liste d'initialisation. La norme C garantit que les éléments restants sont implicitement mis à zéro.
int grille[5][3] = {0};
Ce mécanisme, appelé zero-initialization, fonctionne pour tout type arithmétique. Il est idéal pour les tableaux de taille fixe dont les dimensions sont connues à la compilation.
- Boucles imbriquées explicites
Quand les dimensions ne sont pas connues au moment de l'écriture du code, ou bien quand on travaille sur une zone allouée dynamiquement, les boucles offrent le plus de flexibilité.
#include <stdio.h>
#define HAUTEUR 5
#define LARGEUR 3
int main(void)
{
int grille[HAUTEUR][LARGEUR];
for (int ligne = 0; ligne < HAUTEUR; ligne++) {
for (int colonne = 0; colonne < LARGEUR; colonne++) {
grille[ligne][colonne] = 0;
}
}
for (int ligne = 0; ligne < HAUTEUR; ligne++) {
for (int colonne = 0; colonne < LARGEUR; colonne++) {
printf("%d ", grille[ligne][colonne]);
}
printf("\n");
}
return 0;
}
L'avantage réside dans la maîtrise totale du processus : on peut affecter n'importe quelle valeur, non seulement zéro, et s'adapter à des dimensions déterminées à l'exécution. L'inconvénient est le temps d'exécution proportionnel au nombre d'éléments.
- Fonction
memset()
Pour les matrices de grande taille, la bibliothèque standard fournit memset(), qui remplit un bloc contigu d'octets très rapidement.
#include <stdio.h>
#include <string.h>
#define HAUTEUR 5
#define LARGEUR 3
int main(void)
{
int grille[HAUTEUR][LARGEUR];
memset(grille, 0, sizeof(grille));
for (int ligne = 0; ligne < HAUTEUR; ligne++) {
for (int colonne = 0; colonne < LARGEUR; colonne++) {
printf("%d ", grille[ligne][colonne]);
}
printf("\n");
}
return 0;
}
Il est essentiel de noter que memset() agit octet par octet. Elle est donc sûre pour mettre des entiers à zéro, mais dangereuse pour d'autres valeurs comme 1 ou -1, car chaque octet individuel serait rempli et non chaque entier complet.
- Stockage statique ou global
Les variables globales et les variables locales statiques sont automatiquement initialisées à zéro par le système d'exécution avant l'arrivée dans main().
#include <stdio.h>
#define HAUTEUR 5
#define LARGEUR 3
int grille[HAUTEUR][LARGEUR];
int main(void)
{
for (int ligne = 0; ligne < HAUTEUR; ligne++) {
for (int colonne = 0; colonne < LARGEUR; colonne++) {
printf("%d ", grille[ligne][colonne]);
}
printf("\n");
}
return 0;
}
Cette aprpoche évite toute instruction d'initialisation, mais elle doit être utilisée avec parcimonie : les variables globales augmentent le couplage et compliquent la testabilité du programme.
- Littéraux composés C99
À partir de la norme C99, les littéraux composés permettent d'initialiser un tableau au moment de l'exécution avec une syntaxe proche de l'initialiseur statique.
#include <stdio.h>
#define HAUTEUR 5
#define LARGEUR 3
int main(void)
{
int (*grille)[LARGEUR] = (int[HAUTEUR][LARGEUR]){0};
for (int ligne = 0; ligne < HAUTEUR; ligne++) {
for (int colonne = 0; colonne < LARGEUR; colonne++) {
printf("%d ", grille[ligne][colonne]);
}
printf("\n");
}
return 0;
}
Cette technique allie concision et durée de vie locale. Elle est particulièrement utile dans les fonnes auxiliaires où on veut éviter un tableau global sans écrire de boucles manuelles.
Choisir la bonne méthode
| Méthode | Quand l'utiliser |
|---|---|
{0} |
Tableau de taille fixe, code simple et lisible |
| Boucles | Dimensions variables ou valeur d'initialisation complexe |
memset |
Grands blocs de mémoire à mettre à zéro rapidement |
| Variable globale/statique | Données partagées durant tout le programme |
| Littéral composé | Code moderne, initialisation locale concise |