Pointeurs en C : Qu’est-ce que le pointeur en programmation C ? Les types
⚡ Résumé intelligent
En C, les pointeurs sont des variables qui stockent l'adresse mémoire d'une autre variable. Ils permettent l'allocation dynamique de mémoire, la gestion efficace des tableaux et des chaînes de caractères, ainsi que la création de structures de données complexes, grâce aux opérateurs d'accès et de déréférencement pour lire ou modifier des valeurs.
Qu'est-ce qu'un pointeur en C ?
A aiguille En C, un pointeur est une variable qui stocke l'adresse d'une autre variable. Il peut également pointer vers un autre pointeur ou vers une fonction. Un pointeur peut être incrémenté ou décrémenté pour pointer vers l'emplacement mémoire suivant ou précédent. Son but est d'économiser de l'espace mémoire et d'accélérer l'exécution.
Comment utiliser les pointeurs en C
Si l'on déclare une variable `v` de type `int`, `v` stocke une valeur. Chaque variable, outre sa valeur, possède également une adresse, c'est-à-dire son emplacement en mémoire. On peut récupérer cette adresse en plaçant une esperluette (`&`) devant le nom de la variable. L'adresse d'une variable affichée ressemble à un nombre aléatoire qui peut varier d'une exécution à l'autre.
Au lieu de stocker une valeur, un pointeur stocke l'adresse d'une variable. Par exemple :
int *y = &v;
| VARIABLE | AIGUILLE |
|---|---|
| A La valeur stocké dans un nommé adresse de stockage/mémoire. | A variable qui souligne l'adresse de stockage/mémoire de une variable. |
Déclarer un pointeur
Comme les variables, les pointeurs dans programmation C Les pointeurs doivent être déclarés avant de pouvoir être utilisés. Une déclaration de pointeur a la forme suivante :
data_type *pointer_variable_name;
Ici, Type de données Le type de base du pointeur indique le type de la variable pointée. L'astérisque (*), également utilisé pour la multiplication, est l'opérateur d'indirection qui déclare un pointeur. Voici quelques exemples de déclarations de pointeurs valides :
int *ptr_thing; /* pointer to an integer */ int *ptr1, thing; /* ptr1 points to an int; thing is an int */ double *ptr2; /* pointer to a double */ float *ptr3; /* pointer to a float */ char *ch1; /* pointer to a character */
Initialiser un pointeur
Après avoir déclaré un pointeur, on l'initialise avec l'adresse d'une variable. Si un pointeur n'est pas initialisé et est utilisé, le résultat peut être imprévisible et potentiellement désastreux. Pour obtenir l'adresse d'une variable, utilisez l'opérateur esperluette (&) avant le nom de la variable :
pointer = &variable;
Un programme simple illustrant le fonctionnement d'un pointeur est présenté ci-dessous :
#include <stdio.h> int main() { int a = 10; // variable declaration int *p; // pointer variable declaration p = &a; // store address of a in pointer p printf("Address stored in p is: %x\n", p); // access the address printf("Value stored in p is: %d\n", *p); // access the value return 0; }
Sortie :
Address stored in p is: 60ff08 Value stored in p is: 10
| Opérateur | Sens |
|---|---|
| * | Elle remplit deux fonctions : elle déclare un pointeur et renvoie la valeur de la variable référencée (déréférencement). |
| & | Elle remplit une seule fonction : elle renvoie l’adresse d’une variable. |
Types de pointeurs en C
Pointeur nul
On crée un pointeur nul en lui assignant la valeur NULL lors de sa déclaration. Ceci est utile lorsqu'aucune adresse n'est encore assignée au pointeur. Un pointeur nul contient toujours la valeur 0.
#include <stdio.h> int main() { int *p = NULL; // null pointer printf("The value inside variable p is: %x", p); return 0; }
Pointeur du Vide
Un pointeur void, également appelé pointeur générique, ne possède pas de type de données standard. Il est créé à l'aide du mot-clé void et peut stocker l'adresse de n'importe quelle variable :
#include <stdio.h> int main() { void *p = NULL; // void pointer printf("The size of pointer is: %d\n", sizeof(p)); return 0; }
Pointer sauvage
Un pointeur non initialisé est dit « sauvage ». Ces pointeurs sont inefficaces car ils peuvent pointer vers une adresse mémoire inconnue, ce qui peut entraîner des erreurs et provoquer le plantage du programme. Soyez toujours prudent avec les pointeurs sauvages.
#include <stdio.h> int main() { int *p; // wild pointer printf("%d", *p); return 0; }
Parmi les autres types de pointeurs en C, on trouve le pointeur pendant, le pointeur complexe, le pointeur proche, le pointeur lointain et le pointeur énorme.
Pointeurs d'accès direct et indirect
En C, il existe deux manières équivalentes d'accéder au contenu d'une variable et de le manipuler. L'accès direct utilise directement le nom de la variable, tandis que l'accès indirect utilise un pointeur vers la variable :
#include <stdio.h> int var = 1; /* declare and initialize an int variable */ int *ptr; /* declare a pointer to int */ int main(void) { ptr = &var; /* point ptr to var */ printf("\nDirect access, var = %d", var); printf("\nIndirect access, var = %d", *ptr); *ptr = 48; /* change var through the pointer */ printf("\nIndirect access, var = %d", *ptr); return 0; }
Arithmétique du pointeur en C
Lors de la manipulation de pointeurs, respectez les règles de priorité suivantes. Les opérateurs * et & ont la même priorité que les opérateurs unaires (négation !, incrémentation ++, décrémentation –). Dans une même expression, les opérateurs unaires *, &, !, ++ et – sont évalués de droite à gauche. Si un pointeur P pointe vers une variable X, alors *P peut être utilisé partout où X peut être écrit. Les expressions suivantes sont équivalentes :
| Expression | Expression équivalente |
|---|---|
| Y = *P + 1 | Y = X + 1 |
| *P = *P + 10 | X = X + 10 |
| *P += 2 | X += 2 |
| +++P | ++X |
| (*P)++ | X ++ |
Dans ce dernier cas, les parenthèses sont nécessaires : les opérateurs unaires * et ++ étant évalués de droite à gauche, sans parenthèses, c’est le pointeur P qui serait incrémenté, et non l’objet qu’il pointe. Les opérations arithmétiques disponibles sur les pointeurs sont l’affectation, l’incrémentation et la décrémentation, ainsi que l’addition et la soustraction.tracting un décalage entier, qui déplace le pointeur de ce nombre d'éléments (chaque étape correspond à la taille en octets du type de base).
Pointeurs et tableaux en C avec exemples
Traditionnellement, on accède aux éléments d'un tableau à l'aide d'un index, mais les pointeurs simplifient également cette opération. Un pointeur associé au nom du tableau pointe vers son premier élément :
#include <stdio.h> int main() { int a[5] = {1, 2, 3, 4, 5}; // array initialization int *p; // pointer declaration p = a; // p points to the first element; same as &a[0] for (int i = 0; i < 5; i++) { printf("%d\n", *p); // print element p++; // move to the next element } return 0; }
Ajouter un nombre à un pointeur le décale d'autant d'éléments vers l'avant. Si p pointe vers l'adresse mémoire 0, alors p + 1 fait pointer le pointeur vers l'adresse mémoire 1.
Pointeurs et chaînes C avec exemples
Une chaîne de caractères est un tableau d'objets char se terminant par le caractère nul '\0'. On peut manipuler les chaînes de caractères à l'aide de pointeurs :
#include <stdio.h> #include <string.h> int main() { char str[] = "Hello Guru99!"; char *p; p = str; printf("First character is: %c\n", *p); p = p + 1; printf("Next character is: %c\n", *p); p = str; // reset the pointer for (int i = 0; i < strlen(str); i++) { printf("%c\n", *p); p++; } return 0; }
Une autre façon de manipuler les chaînes de caractères consiste à utiliser un tableau de pointeurs :
#include <stdio.h> int main() { char *materials[] = {"iron", "copper", "gold"}; for (int i = 0; i < 3; i++) printf("%s\n", materials[i]); return 0; }
Avantages des pointeurs en C
- Les pointeurs sont utiles pour accéder directement à des emplacements mémoire.
- Ils offrent un moyen efficace d'accéder aux éléments d'un tableau.
- Ils sont utilisés pour l'allocation et la libération dynamiques de mémoire.
- Ils servent à former des structures de données complexes telles que les listes chaînées, les graphes et les arbres.
Inconvénients des pointeurs en C
- Les pointeurs sont un peu complexes à comprendre.
- Elles peuvent provoquer des erreurs telles que des défauts de segmentation ou un accès à un emplacement mémoire non prévu.
- Une valeur incorrecte attribuée à un pointeur peut entraîner une corruption de la mémoire.
- Les pointeurs sont également responsables des fuites de mémoire si la mémoire n'est pas libérée.
- Il est de la responsabilité du programmeur de manipuler les pointeurs avec soin.

