Plusieurs langages de programmation offrent la possibilité d'accéder aux données dans la mémoire de l'ordinateur à l'aide de pointeurs, c.-à-d. à l'aide de variables auxquelles on peut attribuer les adresses d'autres variables.
En C, les pointeurs jouent un rôle primordial dans la définition de fonctions :
Comme le passage des paramètres en C se fait toujours par la valeur, les pointeurs sont le seul moyen de changer le contenu de variables déclarées dans d'autres fonctions. Ainsi le traitement de tableaux et de chaînes de caractères dans des fonctions serait impossible sans l'utilisation de pointeur.
En outre, les pointeurs nous permettent d'écrire des programmes plus compacts et plus efficients et fournissent souvent la seul solution raisonnable à un problème. Ainsi, la majorité des applications écrites en C profitent des pointeurs.
Dans la programmation, nous utilisons des variables pour stocker des informations. La valeur d'une variable se trouve à un endroit spécifique dans la mémoire interne de l'ordinateur. Le nom de la variable nous permet alors d'accéder directement à cette valeur.
Adressage direct : Accès au contenu d'une variable par le nom de la variable.
Exemple :
short A; A=10
nom |
A |
|||
contenu |
... |
10 |
... |
... |
adresse |
1E04 |
1E06 |
1E08 |
1E0A |
Si nous ne voulons ou ne pouvons pas utiliser le nom d'une variable A, nous pouvons copier l'adresse de cette variable spéciale P, appelée pointeur. Ensuite, nous pouvons retrouver l'information de la variable en passant par le pointeur P.
Adressage indirect : Accès au contenu d'une variable, en passant par un pointeur qui contient l'adresse de la variable.
Exemple : Soient A une variable contenant la valeur 10 et P qui contient l'adresse de A. En mémoire, A et P peuvent se présenter comme suit :
nom |
|
P |
... |
A |
|||
contenu |
|
5C26 |
... |
10 |
|||
adresse |
2AB0 | 2AB2 | 2AB4 | ... | 5C24 | 5C26 | 5C28 |
Lors du travail avec les pointeurs, nous avons besoin :
L'opérateur 'adresse de' : &
& <NomVariable> fournit l'adresse de la variable <NomVariable>.
L'opérateur & nous est déjà familier par la fonction scanf, qui a besoin de l'adresse de ses arguments pour pouvoir leur attribuer de nouvelles valeurs.
Exemple :
int N ; printf (''Entrez un nombre entier :'') ; scanf('' % d, & N) ;
ATTENTION ! ! ! ! !
L'opérateur & peut seulement être appliqué à des objets qui se trouvent dans la mémoire interne, c'est à dire des variables et des tableaux. Il ne peut pas être appliqué à des constantes ou des expressions.
L'opérateur 'contenu de' : *
*<NomPointeur> désigne le contenu de l'adresse référencée par le pointeur <NomPointeur>
Exemple : Soit A une variable contenant la valeur 10, B une variable contenant la valeur 50 et P un pointeur non initialisé :
Après les instructions :
P=&A ; B=*P ; *P=20 ;
Déclaration d'un pointeur :
<Type>*<NomPointeur> déclare un pointeur <NomPointeur> qui peut recevoir des adresses de variables du type <type>.
Une déclaration comme
int *PNUM ;
peut être interprétée comme suit :
Exemple : Le programme complet effectuant les transformations de l'exemple ci-dessus peut se présenter comme suit (2 propositions) :
main() | main() |
{ | { |
/*déclarations*/ | /*déclarations*/ |
short A=10 ; | short A, B, *P ; |
short B=50 ; | /*traitement*/ |
short *P ; | A=10 ; |
/*traitement*/ | B=50 ; |
P=&A ; | P=&A ; |
B=*P ; | B=*P ; |
*P=20 ; | *P=20 ; |
return 0 ; | return 0 ; |
} | } |
En travaillant avec des pointeurs, nous devons observer les règles suivantes :
Priorité de * et &
Les expressions suivantes, sont équivalentes :
Y=*P+1 | Y=X+1 |
*P=*P+10 | X=X+10 |
*P+=2 | X+=2 |
++*P | ++X |
(*P)++ | X++ |
Dans le dernier cas, les parenthèses sont nécessaires :
Comme les opérateurs unaires * et ++ sont évalués de droite à gauche, sans les parenthèses le pointeur P serait incrémenté, non pas l'objet sur lequel P pointe.
On peut uniquement affecter des adresses à un pointeur.
Le pointeur NULL :
Seule exception : La valeur numérique 0 (zéro) est utilisée pour indiquer qu'un pointeur ne pointe 'nulle part' La norme impose d'utiliser la constante NULL.
int *P ; P=NULL ; /* ou P=0; */
Finalement, les pointeurs sont aussi des variables et peuvent être utilisés comme telles. Soit P1 et P2 deux pointeurs sur int, alors l'affectation :
P1=P2 ;
copie le contenu de P2 vers P1. P1 pointe alors sur le même objet que P2.
Résumons
int A ; int*P ; P=&A ;
En outre ;