Les pointeurs en C
Cet article rappel le fonctionnement de l'arithmétique des pointeurs du langage C, spécifique au projet système et son environnement x86 (32 bits).
Bases
Le langage C permet de définir des pointeurs, un pointeur est défini par le type pointé (connu uniquement à la compilation) et une adresse:
1 |
|
L'utilisation du cast permet d'éviter un warning, et surtout d'être clair sur nos intentions.
Dans le code ci-dessus, on pointe vers un entier (int
, 4 octets sur notre architecture) à l'adresse 0x1000. Attention, cela ne signifie pas qu'il existe un entier valide et lisible à cette adresse, cela signifie simplement que l'on peut à souhait écrire sur ou lire depuis ce pointeur.
1 2 |
|
NULL
) provoquera directement une Page Fault.
Arithmétique
Il arrive souvent de vouloir incrémenter ou décaler un pointeur, pour ce faire vous devez garder en tête les règles particulière des opérations arithmétiques (+/-) concernant deux pointeurs (ptr +/- ptr) ou un pointeur et un entier (ptr +/- entier).
Il est par exemple interdit de faire une opération entre deux pointeurs et d'en attendre un pointeur, peu importe leur type. En effet, cela ne fait aucun sens d'obtenir une adresse absolue à partir de deux autres:
1 2 3 4 |
|
Il est cependant possible de faire une soustraction entre deux pointeurs si on attend comme résultat un entier (on peut d'ailleurs choisir le type ptrdiff_t
comme résultat):
1 2 3 4 |
|
Le dernier cas à prendre en compte est l'opération entre un pointeur et un entier, dans ce cas l'entier donné est implicitement multiplié par la taille du type pointé. Pour mieux comprendre, voici un exemple:
1 2 |
|
Dans l'exemple précédent, on incrémente notre pointeur de 1 (car ++
est équivalent de += 1
). Cela signifie dans le cadre de notre pointeur, que celui-ci va se voir incrémenter de 1 * sizeof(int)
, soit 4 octets et non 1. Notre adresse vaut donc après incrément: 0x1004.
Voici une liste d'exemples permettant de mieux comprendre la règle:
1 2 3 |
|