Les pointeurs sont des variables qui stockent l’adresse mémoire d’une autre variable. Ils permettent un accès indirect à la mémoire, offrant ainsi une grande flexibilité dans la manipulation des données en C. Un pointeur de pointeur, comme son nom l’indique, est un pointeur qui pointe vers un autre pointeur.
En C, la déclaration d’un pointeur de pointeur nécessite deux niveaux d’indirection. Voici comment vous pouvez déclarer un pointeur de pointeur :
int **ptr_ptr;
Ici, ptr_ptr
est un pointeur de pointeur vers un entier.
Pour initialiser un pointeur de pointeur, vous devez d’abord allouer de la mémoire pour le pointeur interne, puis assigner son adresse au pointeur de pointeur. Voici un exemple :
int *ptr;
int **ptr_ptr;
int num = 10;
ptr = #
ptr_ptr = &ptr;
Maintenant, ptr_ptr
pointe vers ptr
, qui lui-même pointe vers num
.
Pour accéder à la valeur pointée par un pointeur de pointeur, vous devez déréférencer deux fois. Voici comment vous pouvez accéder à la valeur pointée par ptr_ptr
:
printf("Valeur de num : %d\n", **ptr_ptr);
Les pointeurs de pointeurs sont souvent utilisés dans des situations où une fonction doit modifier un pointeur passé en argument. Par exemple :
void allocateMemory(int **ptr) {
*ptr = (int*)malloc(sizeof(int));
}
int main() {
int *ptr;
allocateMemory(&ptr);
*ptr = 20;
printf("Valeur de la mémoire allouée : %d\n", *ptr);
free(ptr);
return 0;
}
Dans ce cas, la fonction allocateMemory
alloue de la mémoire pour un entier et affecte l’adresse de cette mémoire à ptr
dans la fonction appelante.
N’oubliez pas de libérer la mémoire allouée par les pointeurs de pointeurs pour éviter les fuites de mémoire. Dans l’exemple précédent, nous utilisons free(ptr)
pour libérer la mémoire allouée.
Voici quelques ⭐ cas particuliers ⭐ où les pointeurs de pointeurs en C sont utiles, accompagnés de leur code correspondant :
Les pointeurs de pointeurs sont souvent utilisés pour représenter des tableaux à deux dimensions de manière dynamique. Voici un exemple :
#include <stdio.h>
#include <stdlib.h>
int main() {
int rows = 3, cols = 3;
int **matrix;
matrix = (int **)malloc(rows * sizeof(int *));
for (int i = 0; i < rows; i++) {
matrix[i] = (int *)malloc(cols * sizeof(int));
for (int j = 0; j < cols; j++) {
matrix[i][j] = i * cols + j;
}
}
// Accéder à un élément du tableau à deux dimensions
printf("Element à la position [1][1] : %d\n", matrix[1][1]);
// Libération de la mémoire
for (int i = 0; i < rows; i++) {
free(matrix[i]);
}
free(matrix);
return 0;
}
Ici, matrix
est un pointeur de pointeur qui pointe vers un tableau de pointeurs, chaque pointeur individuel pointant vers un tableau d’entiers.
Les pointeurs de pointeurs sont également utilisés dans les listes chaînées pour mettre à jour les liens entre les nœuds. Voici un exemple simple :
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
void insertAtBeginning(struct Node **head_ref, int new_data) {
struct Node *new_node = (struct Node *)malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = *head_ref;
*head_ref = new_node;
}
void printList(struct Node *node) {
while (node != NULL) {
printf("%d ", node->data);
node = node->next;
}
}
int main() {
struct Node *head = NULL;
insertAtBeginning(&head, 3);
insertAtBeginning(&head, 2);
insertAtBeginning(&head, 1);
printf("Liste : ");
printList(head);
return 0;
}
Dans cet exemple, head
est un pointeur de pointeur qui pointe vers le premier nœud de la liste chaînée. Lorsque nous ajoutons un nouvel élément, nous devons mettre à jour head
en utilisant un pointeur de pointeur.
Les pointeurs de pointeurs en C offrent une grande flexibilité dans la manipulation des données, ce qui les rend utiles dans de nombreux cas, tels que la gestion de tableaux à deux dimensions, les listes chaînées et d’autres structures de données dynamiques. En comprenant leur utilisation, vous pouvez écrire des programmes C plus efficaces et plus expressifs.
Voici quelques ⭐ exemples d’applications ⭐courantes où les pointeurs de pointeurs en C peuvent être utilisés, accompagnés de leur code correspondant :
Les pointeurs de pointeurs sont souvent utilisés pour allouer dynamiquement de la mémoire pour une matrice à deux dimensions. Voici un exemple :
#include <stdio.h>
#include <stdlib.h>
int main() {
int rows = 3, cols = 3;
int **matrix;
// Allocation de mémoire pour les pointeurs de lignes
matrix = (int **)malloc(rows * sizeof(int *));
// Allocation de mémoire pour chaque ligne
for (int i = 0; i < rows; i++) {
matrix[i] = (int *)malloc(cols * sizeof(int));
}
// Utilisation de la matrice
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
matrix[i][j] = i * cols + j;
}
}
// Libération de la mémoire
for (int i = 0; i < rows; i++) {
free(matrix[i]);
}
free(matrix);
return 0;
}
Ici, matrix
est un pointeur de pointeur qui pointe vers une matrice à deux dimensions. Nous utilisons deux niveaux d’indirection pour allouer dynamiquement de la mémoire pour chaque ligne de la matrice.
Les pointeurs de pointeurs sont utiles pour passer un tableau à une fonction en tant qu’argument, car ils permettent à la fonction de modifier le tableau d’origine. Voici un exemple :
#include <stdio.h>
void modifyArray(int **arr, int size) {
for (int i = 0; i < size; i++) {
(*arr)[i] *= 2;
}
}
int main() {
int size = 5;
int *arr = (int *)malloc(size * sizeof(int));
// Initialisation du tableau
for (int i = 0; i < size; i++) {
arr[i] = i;
}
// Appel de la fonction pour modifier le tableau
modifyArray(&arr, size);
// Affichage du tableau modifié
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
free(arr);
return 0;
}
Dans cet exemple, la fonction modifyArray
prend un pointeur de pointeur vers un tableau et modifie les éléments du tableau en les multipliant par 2.
Les pointeurs de pointeurs sont également utilisés dans les listes chaînées pour modifier les liens entre les nœuds. Voici un exemple :
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
void insertAtBeginning(struct Node **head_ref, int new_data) {
struct Node *new_node = (struct Node *)malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->next = *head_ref;
*head_ref = new_node;
}
void printList(struct Node *node) {
while (node != NULL) {
printf("%d ", node->data);
node = node->next;
}
}
int main() {
struct Node *head = NULL;
// Insertion d'éléments au début de la liste
insertAtBeginning(&head, 3);
insertAtBeginning(&head, 2);
insertAtBeginning(&head, 1);
// Affichage de la liste
printf("Liste : ");
printList(head);
return 0;
}
Dans cet exemple, head
est un pointeur de pointeur qui pointe vers le premier nœud de la liste chaînée. Nous utilisons un pointeur de pointeur pour que la fonction insertAtBeginning
puisse modifier la tête de la liste chaînée.
Voici deux ⭐ cas avancés ⭐ où les pointeurs de pointeurs en C peuvent être utilisés de manière avancée :
Les pointeurs de pointeurs peuvent être utilisés pour créer et manipuler des tableaux à dimensions multiples de manière dynamique. Par exemple, un tableau tridimensionnel peut être représenté à l’aide de pointeurs de pointeurs comme suit :
#include <stdio.h>
#include <stdlib.h>
int main() {
int ***array;
int i, j, k;
int dim1 = 2, dim2 = 3, dim3 = 4;
// Allocation de mémoire pour la première dimension
array = (int ***)malloc(dim1 * sizeof(int **));
for (i = 0; i < dim1; i++) {
// Allocation de mémoire pour la deuxième dimension
array[i] = (int **)malloc(dim2 * sizeof(int *));
for (j = 0; j < dim2; j++) {
// Allocation de mémoire pour la troisième dimension
array[i][j] = (int *)malloc(dim3 * sizeof(int));
}
}
// Utilisation du tableau
for (i = 0; i < dim1; i++) {
for (j = 0; j < dim2; j++) {
for (k = 0; k < dim3; k++) {
array[i][j][k] = i * dim2 * dim3 + j * dim3 + k;
}
}
}
// Libération de la mémoire
for (i = 0; i < dim1; i++) {
for (j = 0; j < dim2; j++) {
free(array[i][j]);
}
free(array[i]);
}
free(array);
return 0;
}
Dans cet exemple, array
est un pointeur de pointeur de pointeur qui représente un tableau tridimensionnel. Nous utilisons des boucles pour allouer dynamiquement de la mémoire pour chaque dimension du tableau, puis nous utilisons ces pointeurs de pointeurs pour accéder et manipuler les éléments du tableau.
Les pointeurs de pointeurs peuvent également être utilisés pour créer des tableaux de pointeurs de fonction, ce qui permet une sélection dynamique des fonctions à appeler. Voici un exemple :
#include <stdio.h>
void func1() {
printf("Fonction 1\n");
}
void func2() {
printf("Fonction 2\n");
}
int main() {
void (*func_ptr[2])(); // Tableau de pointeurs de fonction
// Initialisation du tableau de pointeurs de fonction
func_ptr[0] = &func1;
func_ptr[1] = &func2;
// Appel des fonctions à l'aide des pointeurs de pointeurs de fonction
(*func_ptr[0])(); // Appel de func1
(*func_ptr[1])(); // Appel de func2
return 0;
}
Dans ce cas, func_ptr
est un tableau de pointeurs de fonction qui peut contenir des adresses de fonctions. Nous utilisons des pointeurs de pointeurs de fonction pour stocker et appeler dynamiquement des fonctions à partir du tableau.
Voici une série d’exercices conçus pour perfectionner vos compétences Excel. Les corrigés sont inclus pour…
Excel offre plusieurs méthodes pour calculer une moyenne tout en tenant compte des filtres ou…
Excel propose plusieurs fonctions pour insérer ou manipuler la date actuelle. Voici les principales méthodes…
Lorsque des nombres sont stockés sous forme de texte dans Excel, ils ne peuvent pas…
Extraire uniquement les chiffres d'une cellule contenant du texte et des nombres mélangés est une…
Pour supprimer plusieurs caractères spécifiques (par exemple, des symboles, chiffres ou lettres indésirables) dans des…
This website uses cookies.