Tableaux multidimensionnels en C

26 Aug 2019 26 Aug 2019 16043 vues ESSADDOUKI Mostafa 7 min de lecture

Les tableaux multidimensionnels en C

Un tableau multidimensionnel est un tableau dont les éléments sont eux-mêmes des tableaux. On peut le voir comme un ensemble de cases organisées en plusieurs dimensions : lignes, colonnes, profondeur…

Définition — Tableau multidimensionnel Un tableau multidimensionnel est un tableau de tableaux. En C, les éléments sont stockés en mémoire de façon contiguë, ligne par ligne (row-major order). La taille totale est égale au produit de toutes les dimensions multiplié par sizeof(type).

Syntaxe — Déclaration à N dimensions C
type nom_tab[taille1][taille2]...[tailleN];

/* Exemples */
int tab2D[2][3];        /* 2 lignes × 3 colonnes  = 6  éléments */
int tab3D[2][3][4];     /* 2 × 3 × 4              = 24 éléments */
Taille totale d'un tableau multidimensionnel Le nombre d'éléments est le produit de toutes les dimensions. Exemples :
  • int tab[5][3] → 5 × 3 = 15 éléments → 60 octets
  • int tab[2][3][4] → 2 × 3 × 4 = 24 éléments → 96 octets
Formule générale : sizeof(tab) = taille1 × taille2 × … × tailleN × sizeof(type)

1. Tableaux à deux dimensions

Un tableau à deux dimensions est la forme la plus courante. On le visualise comme une grille avec des lignes et des colonnes, similaire à une matrice mathématique.

a. Déclaration


Syntaxe — Tableau 2D C
type Tab[nb_lignes][nb_colonnes];

/* Accès à un élément */
Tab[i][j]   /* ligne i (0 … nb_lignes-1), colonne j (0 … nb_colonnes-1) */

Représentation d'un tableau Tab[3][4] — 3 lignes, 4 colonnes :

Représentation d'un tableau 2D Tab[3][4] avec indices de lignes et colonnes


j = 0j = 1j = 2j = 3
i = 0Tab[0][0]Tab[0][1]Tab[0][2]Tab[0][3]
i = 1Tab[1][0]Tab[1][1]Tab[1][2]Tab[1][3]
i = 2Tab[2][0]Tab[2][1]Tab[2][2]Tab[2][3]

b. Initialisation

Deux méthodes permettent d'initialiser un tableau 2D lors de sa déclaration.

MéthodeCodeRemarque
Liste plateint Tab[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};Remplissage ligne par ligne — moins lisible
Accolades imbriquéesint Tab[3][4] = {{0,1,2,3},{4,5,6,7},{8,9,10,11}};Une paire {} par ligne — recommandée

Exemple n°1 — Les deux méthodes d'initialisation

/* Méthode 1 — liste plate (moins lisible) */
int A[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

/* Méthode 2 — accolades imbriquées (recommandée) */
int B[3][4] = {
    {0,  1,  2,  3},   /* ligne 0 */
    {4,  5,  6,  7},   /* ligne 1 */
    {8,  9, 10, 11}    /* ligne 2 */
};
Astuce — Initialisation partielleComme pour les tableaux 1D, les éléments non spécifiés sont initialisés à zéro. Pour remettre un tableau 2D entier à zéro :
int Tab[3][4] = {0};   /* tous les éléments valent 0 */

c. Accès aux éléments

Exemple n°2 — Modification et affichage d'un élément

#include <stdio.h>

int main(void)
{
    int Tab[3][4] = {
        {0,  1,  2,  3},
        {4,  5,  6,  7},
        {8,  9, 10, 11}
    };

    Tab[0][1] = 8;   /* modification de la ligne 0, colonne 1 */

    printf("Tab[0][1] = %d\n", Tab[0][1]);

    return 0;
}
Sortie
Tab[0][1] = 8

d. Parcours complet avec boucles imbriquées

Pour accéder à tous les éléments d'un tableau 2D, on utilise deux boucles for imbriquées : la boucle externe parcourt les lignes, la boucle interne parcourt les colonnes.

Exemple n°3 — Affichage de tous les éléments

#include <stdio.h>

int main(void)
{
    int Tab[3][4] = {
        {0,  1,  2,  3},
        {4,  5,  6,  7},
        {8,  9, 10, 11}
    };
    int i, j;

    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 4; j++)
        {
            printf("Tab[%d][%d] = %2d\n", i, j, Tab[i][j]);
        }
    }

    return 0;
}
Sortie
Tab[0][0] =  0
Tab[0][1] =  1
Tab[0][2] =  2
Tab[0][3] =  3
Tab[1][0] =  4
Tab[1][1] =  5
Tab[1][2] =  6
Tab[1][3] =  7
Tab[2][0] =  8
Tab[2][1] =  9
Tab[2][2] = 10
Tab[2][3] = 11

Exemple n°4 — Affichage sous forme de grille (plus lisible)

#include <stdio.h>

int main(void)
{
    int Tab[3][4] = {
        {0,  1,  2,  3},
        {4,  5,  6,  7},
        {8,  9, 10, 11}
    };
    int i, j;

    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 4; j++)
            printf("%4d", Tab[i][j]);
        printf("\n");   /* saut de ligne après chaque ligne */
    }

    return 0;
}
Sortie
   0   1   2   3
   4   5   6   7
   8   9  10  11

2. Stockage en mémoire (row-major)

En C, un tableau 2D est stocké en mémoire ligne par ligne (row-major order) : tous les éléments de la ligne 0 d'abord, puis la ligne 1, etc.

Ordre de stockage — Tab[3][4]
/* En mémoire : 12 cases consécutives */
Tab[0][0] Tab[0][1] Tab[0][2] Tab[0][3]
Tab[1][0] Tab[1][1] Tab[1][2] Tab[1][3]
Tab[2][0] Tab[2][1] Tab[2][2] Tab[2][3]

/* Formule d'adresse */
adresse(Tab[i][j]) = adresse(Tab) + (i × nb_colonnes + j) × sizeof(int)

Exemple n°5 — Vérification des adresses consécutives

#include <stdio.h>

int main(void)
{
    int Tab[2][3] = {{1, 2, 3}, {4, 5, 6}};
    int i, j;

    for (i = 0; i < 2; i++)
        for (j = 0; j < 3; j++)
            printf("Tab[%d][%d] = %d  @ adresse %p\n",
                   i, j, Tab[i][j], (void *)&Tab[i][j]);

    return 0;
}
Sortie
Tab[0][0] = 1  @ adresse 0x7fff...00
Tab[0][1] = 2  @ adresse 0x7fff...04  (+4)
Tab[0][2] = 3  @ adresse 0x7fff...08  (+4)
Tab[1][0] = 4  @ adresse 0x7fff...0c  (+4)
Tab[1][1] = 5  @ adresse 0x7fff...10  (+4)
Tab[1][2] = 6  @ adresse 0x7fff...14  (+4)

3. Opérations classiques sur les matrices

Exemple n°6 — Saisie d'une matrice au clavier

#include <stdio.h>
#define NL 3
#define NC 4

int main(void)
{
    int Tab[NL][NC];
    int i, j;

    printf("Entrer les %d éléments :\n", NL * NC);

    for (i = 0; i < NL; i++)
        for (j = 0; j < NC; j++)
        {
            printf("Tab[%d][%d] = ", i, j);
            scanf("%d", &Tab[i][j]);
        }

    /* Affichage sous forme de grille */
    printf("\nMatrice :\n");
    for (i = 0; i < NL; i++)
    {
        for (j = 0; j < NC; j++)
            printf("%4d", Tab[i][j]);
        printf("\n");
    }

    return 0;
}

Exemple n°7 — Addition de deux matrices carrées

#include <stdio.h>
#define N 3

int main(void)
{
    int A[N][N] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    int B[N][N] = {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}};
    int C[N][N];
    int i, j;

    /* Addition élément par élément */
    for (i = 0; i < N; i++)
        for (j = 0; j < N; j++)
            C[i][j] = A[i][j] + B[i][j];

    /* Affichage du résultat */
    printf("A + B =\n");
    for (i = 0; i < N; i++)
    {
        for (j = 0; j < N; j++)
            printf("%4d", C[i][j]);
        printf("\n");
    }

    return 0;
}
Sortie
A + B =
  10  10  10
  10  10  10
  10  10  10

4. Tableaux à trois dimensions

Un tableau 3D peut être vu comme un ensemble de matrices 2D empilées. L'accès se fait avec trois indices : Tab[profondeur][ligne][colonne].


Syntaxe — Tableau 3D C
type Tab[p][n][m];   /* p "couches" de matrices n×m */

/* Initialisation */
int Tab[2][2][3] = {
    {{1, 2, 3}, {4, 5, 6}},    /* couche 0 */
    {{7, 8, 9}, {10,11,12}}    /* couche 1 */
};

Exemple n°8 — Parcours d'un tableau 3D

#include <stdio.h>

int main(void)
{
    int Tab[2][2][3] = {
        {{1, 2, 3}, {4, 5, 6}},
        {{7, 8, 9}, {10, 11, 12}}
    };
    int k, i, j;

    for (k = 0; k < 2; k++)
    {
        printf("Couche %d :\n", k);
        for (i = 0; i < 2; i++)
        {
            for (j = 0; j < 3; j++)
                printf("%4d", Tab[k][i][j]);
            printf("\n");
        }
        printf("\n");
    }

    return 0;
}
Sortie
Couche 0 :
   1   2   3
   4   5   6

Couche 1 :
   7   8   9
  10  11  12

5. Passer un tableau 2D à une fonction

Lors du passage d'un tableau 2D à une fonction, le nombre de colonnes doit être spécifié — seule la première dimension peut être omise.


Syntaxe — Passage de tableau 2D à une fonction C
/* Le nombre de colonnes DOIT être spécifié */
void afficher(int Tab[][4], int lignes);

/* Appel */
afficher(Tab, 3);

Exemple n°9 — Fonction d'affichage d'une matrice

#include <stdio.h>
#define NC 4

void afficher(int Tab[][NC], int nl)
{
    int i, j;
    for (i = 0; i < nl; i++)
    {
        for (j = 0; j < NC; j++)
            printf("%4d", Tab[i][j]);
        printf("\n");
    }
}

int main(void)
{
    int M[3][NC] = {{0,1,2,3},{4,5,6,7},{8,9,10,11}};
    afficher(M, 3);
    return 0;
}
Sortie
   0   1   2   3
   4   5   6   7
   8   9  10  11
Danger — Omettre le nombre de colonnes En C, oublier de préciser le nombre de colonnes dans la signature provoque une erreur de compilation car le compilateur ne peut pas calculer l'adresse de Tab[i][j]:
void afficher(int Tab[][], int nl)   /* erreur — colonnes manquantes */

Récapitulatif

ConceptSyntaxe / RèglePoint clé
Déclaration 2Dint Tab[nl][nc];Indices de 0 à nl−1 et 0 à nc−1
Initialisation recommandée{{…},{…},{…}}Accolades imbriquées — une paire par ligne
Accès à un élémentTab[i][j]Ligne i, colonne j
Parcours completDeux boucles for imbriquéesExterne = lignes, Interne = colonnes
Stockage mémoireRow-major (ligne par ligne)adresse = base + (i×nc + j)×sizeof(type)
Taille totalesizeof(Tab)nl × nc × sizeof(type) octets
Passage à une fonctionvoid f(int Tab[][nc], int nl)Nombre de colonnes obligatoire
Tableau 3Dint Tab[p][nl][nc]p couches de matrices nl×nc

Discussion (0)

Soyez le premier à laisser un commentaire !

Laisser un commentaire

Votre commentaire sera visible après modération.