Précision importante
1. une adresse n’est jamais à priori l’équivalent d’une simple position dans la mémoire.
2. La taille en octets des adresses sizeof(T*) dépend du modèle de compilation choisi avec
le compilateur utilisé. Avec la taille des mémoires actuelles sur les ordinateurs
personnels, toutes les adresses sont normalement gardées sur quatre octets. En
ingénierie, la programmation sur de toutes petites (micro)plate-formes se fait encore
avec des adresses plus petites.
Comment obtenir des adresses dans un programme
1. Avec l’opérateur & : L’expression obtenue de l’opérateur & en préfixe à une variable de
type T est évaluée comme une adresse de type T*. Cet opérateur est utilisé avant
tout lors du passage de paramètres par référence à une fonction. Note très
technique…. la classe d’allocation register et l’opérateur & sont incompatibles.
2. À l’aide du nom d’un tableau : Dans une expression, le nom d’un tableau contenant des
objets de type T est automatiquement évalué comme une adresse de type T*
correspondant à l’adresse du premier élément du tableau. – ce qui explique qu’un tableau
utilisé en paramètre effectif puisse être modifié à travers le paramètre formel dans la fonction –
3. Par arithmétique des adresses : À l’aide de tout opérateur d’ addition ou de
soustraction des entiers (+ - ++ -- += -= ), on peut obtenir une nouvelle adresse. Une
section plus bas décrit toute l’arithmétique des adresses.
4. Par allocation programmée : En Run Time du programme, la fonction classique
malloc permet la demande au système d’exploitation d’un bloc d’octets de la taille
donnée en paramètre. La fonction malloc retourne en cas de succès l’adresse (void*) du
premier octet du bloc d’octets offert alors par l’OS dans le heap de la machine (c’est la
partie de la mémoire non-utilisée lors de la demande) ou la constante symbolique NULL en
cas d’échec. Ces blocs d’octets n’ont pas de classe d’allocation, de « storage class » qui
définit normalement la durée de vie et l’accessibilité de toute mémoire obtenue
automatiquement en compilation (Compile time) pour le programme. Ces blocs de
mémoire obtenus dynamiquement (synonyme d’allocation programmée) sont tous à la
charge du programmeur qui devra les libérer explicitement avec la fonction free une fois
leur usage complété. La perte par le programmeur d’une adresse obtenue en allocation
programmée amène une perte très réelle de mémoire « dite memory leak » de la
machine hôte pendant toute l’exécution du programme. Ces bugs sont pervers et
amènent implacablement au plantage de l’application.
5. À l’aide du nom d’une fonction : Dans une expression, le nom d’une fonction donne
l’adresse du premier octet de son code. Le type de cette adresse est associé à la
déclaration de la fonction. Le nom d’une fonction pourra donc servir de paramètre
effectif et cette fonction pourra être déclenchée avec son paramètre formel
correspondant.
6. Par transtypage : Le transtypage (typecasting) d’une adresse correcte donne une
adresse différente. La position n’est pas changée mais le contenu est différent. La forme
la plus correcte devrait se faire en transitant par void*. Peu importe le type de l’adresse
addr, l’expression (T1*)(void*) addr sera de type T1* . Aucun compilateur ne
donne de limites à ces transtypages. Tout transtypage d’adresse est potentiellement
dangereux et le programmeur en est totalement responsable, donc un transtypage
d’adresse DOIT TOUJOURS être abondamment commenté.
7. Par adressage absolu : Un entier peut être considéré comme une adresse. Par exemple,
l’expression (int*)(void *) 1600 permet d’avoir accès à un entier à l’octet numéro
1600 en mémoire. Cette pratique n’est rencontrée qu’en programmation sur de micro-
plateformes , elle est absolument NON PORTABLE et interdite dans notre cours.