Tableaux multidimensionnels et pointeurs
Deux/trois dimensions, disposition mémoire et calcul d’index via pointeurs.
En C++, les tableaux à plusieurs dimensions (par exemple les matrices) permettent d’organiser les données sous forme de tableau ou de grille. Les tableaux multidimensionnels sont stockés de manière contiguë en mémoire et peuvent être accessibles directement à l’aide de pointeurs. Dans cet article, nous allons apprendre la relation entre les tableaux 2D et 3D et les pointeurs, les techniques d’accès, et comment créer des matrices dynamiques.
1. Tableaux bidimensionnels (2D)
Les tableaux à deux dimensions sont généralement représentés sous forme de lignes et de colonnes. L’exemple suivant définit une matrice de 2 lignes × 3 colonnes :
#include <iostream>
using namespace std;
int main() {
int matrice[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
cout << matrice[0][1] << endl; // 2
cout << matrice[1][2] << endl; // 6
}
Dans cet exemple, matrice[0][1] représente la valeur de la première ligne, deuxième colonne.
Comme les tableaux C++ commencent à 0, [1][2] correspond en réalité à la deuxième ligne, troisième colonne.
2. Organisation en mémoire
C++ stocke les tableaux multidimensionnels en mémoire selon l’ordre row-major (par ligne). Cela signifie que chaque ligne est placée de manière contiguë dans la mémoire :
Disposition mémoire :
matrice[0][0], matrice[0][1], matrice[0][2],
matrice[1][0], matrice[1][1], matrice[1][2]
Grâce à cela, il est possible d’accéder à tous les éléments du tableau en utilisant l’arithmétique des pointeurs comme s’il s’agissait d’un tableau unidimensionnel.
3. Accès aux éléments d’un tableau 2D avec des pointeurs
Les tableaux multidimensionnels sont essentiellement des chaînes de pointeurs.
Par exemple, dans int matrice[2][3], matrice contient l’adresse d’un tableau int[3].
#include <iostream>
using namespace std;
int main() {
int matrice[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
cout << *(*(matrice + 0) + 1) << endl; // 2
cout << *(*(matrice + 1) + 2) << endl; // 6
}
matrice→ pointe vers la première ligne.*(matrice + 1)→ passe à la deuxième ligne.*(*(matrice + 1) + 2)→ accède à la valeur de la deuxième ligne, troisième colonne.
4. Parcourir avec des pointeurs
Il est possible de parcourir les éléments d’une matrice en utilisant l’arithmétique des pointeurs.
int matrice[2][3] = {{10,20,30},{40,50,60}};
int *ptr = &matrice[0][0];
for (int i = 0; i < 6; i++) {
cout << *(ptr + i) << " ";
}
Sortie :
10 20 30 40 50 60
Comme on peut le voir, le tableau 2D est stocké sous forme d’un seul bloc mémoire, il est donc possible d’accéder à tous les éléments avec un seul pointeur.
5. Passer un tableau multidimensionnel à une fonction
Les tableaux 2D peuvent être passés en paramètre à une fonction. Cependant, en C++, il est obligatoire d’indiquer la deuxième dimension (le nombre de colonnes).
void Afficher(int tab[][3], int lignes) {
for (int i = 0; i < lignes; i++) {
for (int j = 0; j < 3; j++) {
cout << tab[i][j] << " ";
}
cout << endl;
}
}
int main() {
int matrice[2][3] = {{1,2,3},{4,5,6}};
Afficher(matrice, 2);
}
Une autre approche consiste à utiliser la syntaxe des pointeurs :
void Afficher(int (*p)[3], int lignes) {
for (int i = 0; i < lignes; i++)
for (int j = 0; j < 3; j++)
cout << p[i][j] << " ";
}
Ici, int (*p)[3] signifie “pointeur vers un tableau de 3 entiers”.
6. Tableaux tridimensionnels (3D)
Les tableaux 3D sont des collections de tableaux 2D.
Par exemple, int espace[2][3][4] représente 2 matrices de taille 3×4.
#include <iostream>
using namespace std;
int main() {
int espace[2][3][4] = {
{ {1,2,3,4}, {5,6,7,8}, {9,10,11,12} },
{ {13,14,15,16}, {17,18,19,20}, {21,22,23,24} }
};
cout << espace[1][2][3] << endl; // 24
}
Les tableaux 3D sont souvent utilisés dans le traitement graphique, les moteurs de jeux et les calculs scientifiques.
7. Création dynamique d’un tableau 2D (matrice)
Pour créer des matrices dont la taille n’est pas connue à la compilation,
on peut utiliser l’opérateur new avec des tableaux de pointeurs.
#include <iostream>
using namespace std;
int main() {
int lignes = 2, colonnes = 3;
int **matrice = new int*[lignes]; // tableau de pointeurs de lignes
for (int i = 0; i < lignes; i++)
matrice[i] = new int[colonnes]; // créer chaque ligne
// assignation de valeurs
for (int i = 0; i < lignes; i++)
for (int j = 0; j < colonnes; j++)
matrice[i][j] = (i+1)*(j+1);
// affichage
for (int i = 0; i < lignes; i++) {
for (int j = 0; j < colonnes; j++)
cout << matrice[i][j] << " ";
cout << endl;
}
// libération de la mémoire
for (int i = 0; i < lignes; i++)
delete[] matrice[i];
delete[] matrice;
}
Cette méthode permet de définir la taille de la matrice dynamiquement à l’exécution (par exemple à partir d’une entrée utilisateur).
Mais il faut se souvenir que chaque new[] doit avoir un delete[] correspondant.
8. Alternative moderne : std::vector<vector<int>>
En C++, la manière la plus sûre et la plus simple de créer une matrice dynamique consiste à utiliser std::vector.
#include <iostream>
#include <vector>
using namespace std;
int main() {
int lignes = 2, colonnes = 3;
vector<vector<int>> matrice(lignes, vector<int>(colonnes));
for (int i = 0; i < lignes; i++)
for (int j = 0; j < colonnes; j++)
matrice[i][j] = (i+1) + (j+1);
for (auto &ligne : matrice) {
for (int valeur : ligne)
cout << valeur << " ";
cout << endl;
}
}
std::vector gère automatiquement la mémoire,
ne nécessite ni delete[] ni new, et peut facilement être redimensionné.
9. TL;DR
- Les tableaux 2D sont stockés ligne par ligne en mémoire (ordre row-major).
*(matrice + i) + jest équivalent àmatrice[i][j].- La deuxième dimension doit être précisée dans les paramètres de fonction.
- Les tableaux 3D sont des ensembles de tableaux 2D :
int espace[2][3][4]. - Les matrices dynamiques peuvent être créées avec
new/delete[]. - En C++ moderne,
std::vector<vector<>>est recommandé. - Tous les exemples peuvent être exécutés sous Visual Studio 2022 ou GCC 11+.