Programmation séquentielle en C, 2020-2021
Orestis Malaspinas (A401), ISC, HEPIA
2020-10-14
Un pointeur est une adresse mémoire.
Pour interpréter le contenu de ce qu’il pointe, il doit être typé.
Un pointeur n’est rien d’autre qu’un entier (64bit sur x86-64, soit 8 octets).
Un pointeur peut être déréférencé: on accède à la valeur située à l’adresse mémoire sur laquelle il pointe.
NULL
(ou 0
) est la seule adresse toujours invalide.
Permettent d’accéder à une valeur avec une indirection.
Permettent d’avoir plusieurs chemins d’accès à une valeur.
Lire et écrire en même temps dans un bout de mémoire devient possible: danger.
const
Le mot clé const
permet de déclarer des valeurs “constantes” qui ne changeront plus en cours d’exécution du programme.
Mais qu’est-ce que cela veut dire pour les pointeurs?
int n = 12; int m = 13;
const int *p = &n; // la valeur *p est const, p non
*p = m; // erreur de compilation.
p = &m; // OK
int const *p = &n; // la valeur *p est const, p non
*p = m; // erreur de compilation.
p = &m; // OK
int *const p = &n; // la valeur p est const, *p non
*p = m; // OK
p = &m; // erreur de compilation.
const int *const p = &n; // la valeur p et *p sont const
*p = m; // erreur de compilation.
p = &m; // erreur de compilation.
sizeof()
(1/2)sizeof()
permet de connaître la taille en octets:
int a = 2
, sur l’architecture x86_64 que vaut:
sizeof(a)
?sizeof(&a)
?char b = 2
,
sizeof(b)
?sizeof(&b)
?sizeof()
(2/2)sizeof(a) == 4
, int
entier 32 bits.sizeof(&a) == 8
, une adresse est de 64 bits.sizeof(b) == 1
, char
entier 8 bits.sizeof(&b) == 8
, une adresse est de 64 bits.La fonction malloc
permet d’allouer dynamiquement (pendant l’exécution du programme) une zone de mémoire contiguë.
size
est la taille de la zone mémoire en octets.
Retourne un pointeur sur la zone mémoire ou NULL
en cas d’échec: toujours vérifier que la valeur retournée est != NULL
.
On peut allouer un complex_t
:
La zone mémoire n’est pas initialisée.
La mémoire doit être désallouée explicitement ⇒ fuites mémoires.
La fonction free()
permet de libérer une zone préalablement allouée avec malloc()
.
Pour chaque malloc()
doit correspondre exactement un free()
.
Si la mémoire n’est pas libérée: fuite mémoire (l’ordinateur plante quand il y a plus de mémoire).
Si la mémoire est libérée deux fois: seg. fault.
Pour éviter les mauvaises surprises mettre ptr
à NULL
.
Pour allouer un espace mémoire de 50 entiers:
Cette espace peut alors être utilisé comme un tableau de 50 entiers:
On peut parcourir la mémoire différemment qu’avec l’indexation
Tout comme une valeur a une adresse, un pointeur a lui-même une adresse:
Chaque *
ou &
rajoute une indirection.
Avec malloc()
, on peut allouer dynamiquement des tableaux de pointeurs:
Ceci est une matrice (un tableau de tableau).
Il existe différents outils pour détecter les problèmes mémoire:
Notamment:
Ici on utilise les sanitizers (modification de la ligne de compilation):
Attention: Il faut également faire l’édition des liens avec les sanitizers.