Introduction à la notion de pointeur

Introduction à la notion de pointeur

Pile

2/10/2019

note: ce document n'est pas un cours de langage évolué, il introduit les concepts nécessaires à la compréhension de ce qui est utilisé en langage machine pour accéder à un tableau.

Notion de tableau

Un tableau est une zone de mémoire réservée à l'usage exclusif d'un ensemble de données semblables accédées par un rang.

Toutes les données sont du même type, elles sont rangées consécutivement dans cette zone de mémoire les unes derrière les autres, sans espaces.

Par exemple, on a un tableau de 32 données d'un octet, on peut accéder à chacun des octets en précisant où l’élément se situe dans le tableau par son rang. Le premier élément du tableau a le rang 0 et le dernier a le rang (Taille_du_tableau - 1).

En langage évolué

char tab[32]; // déclaration d'un tableau de caractère
...
tab[2] = 'A'; // On valorise le troisième octet avec le caractère A

En assembleur

        segment byte at: 80-FF ‘RAM0’
tab     ds.b    32  ; declaration d'un tableau de caractere
...
        segment byte at: 8080-FFFF ‘FLASH’
...
        LD A,#$41
        LD {tab+2},A ; On valorise le troisième octet avec le caractère A

Notion de pointeur

Par définition un pointeur est une variable contenant une adresse.

En langage évolué (C), un pointeur est caractérisé par le type de la valeur pointé; cela est fait dans sa déclaration.

char* pchar; // pointeur de caractère
int* pint; // pointeur d'entier signé
unsigned int* puint; //pointeur d'entier non signé

char tab[32]; // déclaration d'un tableau de caractère
char ch1; // déclaration d'une variable contenant un caractère
int in2; // Déclaration d'un entier

En assembleur, un pointeur est une zone mémoire réservée qui contient une adresse ( long ou extended), il ne lui est pas associé de type (ATTENTION DANGER!) et est défini par une étiquette.

Par exemple en se limitant à l'espace d'adressage long.

        segment byte at: 80-FF ‘RAM0’
...
pchar   ds.w        ; pointeur en adressage long (2octets)
pint    ds.w        ; pointeur en adressage long
...

Référencement

En tant que variable, un pointeur peut être affecté d'une valeur ou on peut en lire sa valeur.

pchar = &ch1; // L'opérateur & produit l'adresse de l'opérande qui est rangé dans le pointeur
pchar = &tab[0]; // On valorise pchar avec l'adresse du premier élément du tableau
pchar = tab; // Simplification d'écriture tab <=> &tab[0] 

pchar2 = pchar; // On peut affecter un pointeur avec la valeur d'un autre pointeur de même type

pint = (int*) pchar; // Exceptionnellement On peut contourner la protection de type en transtypant

L'opérateur "&" permet d'obtenir l'adresse de l'opérande ( cela s’appelle le référencement).

En assembleur, on charge le pointeur dans un registre d'index (X) et on utilise ensuite l'adressage indexé.

        segment byte at: 8080-FFFF ‘FLASH’
...
        LDW X,#tab   ; on charge X avec l'adresse de tab
        LDW pchar,X ; On le range dans la variable pointeur
        LDW pint,X  ; Et malheureusement on peut ecraser un pointeur d'entier par un pointeur de caractere

Déréférencement

Le pointeur permet d'obtenir la valeur pointée ou de la modifier, pour cela il est défini en C l'opérateur de déréférencement "*".

   *pchar = 'A';
   *pchar2 = *pchar;

En assembleur c'est très simple.

        segment byte at: 8080-FFFF ‘FLASH’
...
        LDW X,pchar  ; *pchar = 'A'; => on charge X avec la valeur du pointeur
        LD A,#$41   ; On charge 'A' dans A
        LDW (X),A    ; Et on ecrit dans l'emplacement pointe
...
        LDW X,pchar  ; *pchar2=*pchar => on charge X avec la valeur du pointeur
        LD A,(X)    ; On charge *pchar
        LDW X,pchar2  
        LD (X),A    ; Et on ecrit dans l'emplacement pointe

Incrémentation et décrémentation

Enfin les pointeurs disposent deux opérateurs spécifiques l'incrémentation "++" et la décrémentation "--".

En langage évolué, l'incrémentation augmente la valeur du pointeur de la taille d'un élément pointé et réciproquement la décrémentation diminue la valeur du pointeur de la taille d'un élément pointé.

unsigned int tuint[12];
unsigned int* puint;
...
puint = &tuint[6];
puint++; // maintenant puint pointe tuint[7]
printf( "%u", *puint); // impression de tuint[7]
puint--; // retour sur tuint[6]

En assembleur on va incrémenter l'index après l'avoir chargé de la valeur du pointeur

        LDW X,#{tuint+12}  ; puint = &tuint[6]; => on charge X avec l'adresse du septieme element
        LDW puint,X        ; on range X dans le pointeur
...
        LDW X,puint        ; puint++;
        ADDW X,#$0002      ; on incremente X de la longueur d'un element pointe
        LDW puint,X        ; on range X dans le pointeur