int main() {
int mon_numéro =10 ;
int *ptr; // Déclare un pointeur vers un entier
ptr =&mon_numéro; // Attribue l'adresse de mon_numéro au pointeur ptr
printf("Valeur de mon_numéro :%d\n", mon_numéro);
printf("Adresse de mon_numéro :%p\n", &mon_numéro); // %p est le spécificateur de format pour l'impression des adresses
printf("Valeur de ptr :%p\n", ptr);
printf("Valeur pointée par ptr :%d\n", *ptr); // Déréférencement du pointeur
renvoie 0 ;
}
```
Sortie (varie en fonction du système) :
```
Valeur de mon_numéro :10
Adresse de mon_numéro :0x7ffc94b2d8a0
Valeur du ptr :0x7ffc94b2d8a0
Valeur pointée par ptr :10
```
Explication :
1. `int mon_numéro =10;` :Déclare une variable entière `my_number` et l'initialise à 10. Le compilateur alloue un emplacement mémoire pour stocker cette variable.
2. `int *ptr;` :Déclare une variable de pointeur `ptr` conçue pour contenir l'adresse d'une variable entière.
3. `ptr =&mon_numéro;` :C'est là que l'opérateur d'adresse entre en jeu. `&my_number` est évalué à l'adresse mémoire où `my_number` est stocké. Cette adresse est ensuite attribuée à la variable pointeur `ptr`. Maintenant, `ptr` *pointe vers* `my_number`.
4. `printf("Adresse de mon_numéro :%p\n", &mon_numéro);` :Imprime l'adresse mémoire de `my_number` en utilisant le spécificateur de format `%p`.
5. `printf("Valeur de ptr :%p\n", ptr);` :Imprime la valeur stockée dans `ptr`, qui est l'adresse de `my_number`. Notez que l'adresse imprimée ici est la même que l'adresse de « mon_numéro ».
6. `printf("Valeur pointée par ptr :%d\n", *ptr);` :Cette ligne montre le *déréférencement* du pointeur. L'opérateur `*`, lorsqu'il est utilisé avec un pointeur, accède à la valeur stockée à l'emplacement mémoire pointé par le pointeur. Ainsi `*ptr` accède à la valeur de `my_number` (qui est 10).
Utilisations courantes de l'opérateur d'adresse :
1. Pointeurs : Comme indiqué ci-dessus, l'opérateur d'adresse est fondamental pour travailler avec des pointeurs. Les pointeurs stockent les adresses mémoire et l'opérateur d'adresse fournit ces adresses.
2. Appels de fonctions par référence : C prend en charge les appels de fonction par valeur et par référence. Pour passer une variable par référence, vous transmettez son adresse à la fonction. La fonction peut alors modifier la variable d'origine à l'aide du pointeur qu'elle reçoit.
```c
#include
void incrément (int * nombre) {
(*nombre)++; // Incrémente la valeur à l'adresse pointée par 'numéro'
}
int main() {
entier x =5 ;
printf("Avant l'incrément :%d\n", x);
incrément(&x); // Passe l'adresse de x à la fonction d'incrémentation
printf("Après l'incrément :%d\n", x);
renvoie 0 ;
}
```
Dans cet exemple, `increment` modifie le `x` d'origine car il reçoit un pointeur vers `x` (c'est-à-dire son adresse).
3. Allocation dynamique de mémoire : Lorsque vous allouez de la mémoire dynamiquement à l'aide de fonctions telles que `malloc()`, vous travaillez avec des pointeurs vers la mémoire allouée. L'opérateur d'adresse est souvent utilisé implicitement lorsque vous transmettez un pointeur vers la mémoire allouée dynamiquement aux fonctions.
```c
#include
#include
int main() {
int *arr;
taille entière =5 ;
// Alloue de la mémoire pour un tableau de 5 entiers
arr =(int*)malloc(taille * taillede(int));
si (arr ==NULL) {
printf("L'allocation de mémoire a échoué !\n");
renvoyer 1 ;
}
// Accéder aux éléments du tableau en utilisant l'arithmétique du pointeur
pour (int i =0; i
arr[je] =je * 2;
}
// Imprimer les éléments du tableau
pour (int i =0; i
printf("arr[%d] =%d\n", je, *(arr + je)); //*(arr + i) est équivalent à arr[i]
}
gratuit(arr); // Libère la mémoire allouée dynamiquement
renvoie 0 ;
}
```
`malloc` renvoie un pointeur vide qui doit ensuite être converti en type de données approprié, `(int*)` dans ce cas. La variable `arr` contient désormais l'adresse de début du bloc mémoire alloué.
4. Structures et syndicats : Vous pouvez utiliser l'opérateur d'adresse pour obtenir l'adresse d'une variable de structure ou d'union. Ceci est essentiel pour transmettre des structures à des fonctions par référence ou pour créer des pointeurs vers des structures.
```c
#include
Point de structure {
entier x ;
int y;
} ;
int main() {
struct Point p ={10, 20} ;
struct Point *ptr_p =&p; // Récupère l'adresse de la structure Point
printf("Adresse de p :%p\n", &p);
printf("Adresse du p.x :%p\n", &p.x); // Adresse du membre x
printf("Adresse de p.y :%p\n", &p.y); // Adresse du membre y
ptr_p->x =5 ; // Accédez au membre x à l'aide du pointeur
ptr_p->y =15 ; // Accédez au membre y à l'aide du pointeur
printf("p.x :%d, p.y :%d\n", p.x, p.y); // Sortie :p.x :5, p.y :15
renvoie 0 ;
}
```
Considérations importantes :
* Valeurs L : L'opérateur d'adresse ne peut être appliqué qu'à ce qu'on appelle une « valeur l ». Une valeur l est une expression qui fait référence à un emplacement mémoire, tel qu'une variable, un élément de tableau ou un champ dans une structure. Vous ne pouvez pas appliquer l'opérateur d'adresse à une constante ou à une valeur temporaire produite par une expression (par exemple, `&(5 + 3)` n'est pas valide).
* Type de données : L'opérateur d'adresse renvoie un pointeur dont le type de données est le type de données de la variable à laquelle il est appliqué. Par exemple, `&my_number` (où `my_number` est un `int`) renvoie un `int*`.
En résumé, l'opérateur d'adresse (`&`) est un opérateur fondamental en C qui permet d'accéder à l'emplacement mémoire d'une variable. Il est essentiel pour la manipulation de pointeurs, les appels de fonctions par référence, l'allocation dynamique de mémoire et l'utilisation de structures et d'unions. Comprendre son objectif et ses fonctionnalités est crucial pour écrire des programmes C efficaces et robustes.