SIF1053 Architecture des ordinateurs Sujets Notions de pointeurs
- Slides: 38
SIF-1053 Architecture des ordinateurs Sujets • • Notions de pointeurs en C Notions de base sur les pointeurs Pointeurs et Tableaux (matrices) Arithmétiques sur les pointeurs Chaînes de caractères Tableaux à deux dimensions Tableaux de pointeurs Allocation de mémoire Références: http: //www. cplus. com/doc/tutorial/pointers. html http: //www. cs. cf. ac. uk/Dave/C/node 10. html http: //pweb. netcom. com/~tjensen/ptr/pointers. htm http: //www. commentcamarche. net/c/cpoint. php 3 http: //www. iu. hio. no/~mark/CTutorial. html
Notions de base des pointeurs • Si nous voulons permuter le contenu de deux variables entières x et y, nous permuterons ces variables à l’aide d’une fonction "swap(x, y)" qui permet la permutation des variables x et y (les paramètres). • La version suivante de cette fonction ne fonctionne pas car même si on modifie x et y, les nouvelles valeurs permutées ne sont pas retransmises à la fin de la fonction: void swap(int x, int y) { int temp; temp=x; x=y; y=temp; }
Notions de base des pointeurs • Version fonctionnelle: void swap(int *px, int *py) { int temp; temp=*px; *px=*py; *py=temp; } • Appel à la procédure swap(): int x=3, y=5; swap(&x, &y); // &x: & retourne l'adresse de la variable x // x=5 et y=3 au retour du swa. P()
Notions de base des pointeurs • La plupart des langages de programmation offrent la possibilité d'accéder aux données dans la mémoire de l'ordinateur à l'aide de pointeurs, Un pointeur est une variable affectée à la valeur d’un adresse. • En C, les pointeurs jouent un rôle primordial dans la définition de fonctions • Sachant que le passage des paramètres en C se fait toujours par valeur, • Les pointeurs permettent de passer une référence sur un objet à une fonction appelée. • Le pointeur permet donc 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 pointeurs.
Notions de base des pointeurs • Modes d’adressage • Adressage direct : – 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 (RAM) de l'ordinateur. – Le nom de la variable nous permet alors d'accéder directement à cette valeur. – Donc l’adressage direct permet l’accès au contenu d'une variable par le nom de la variable. • Adressage indirect : – Accès au contenu d'une variable, en passant par un pointeur qui contient l'adresse de la variable. – Donc l’accès à une valeur d’une variable se fait par l’accès préalable au contenu d’un pointeur.
Notions de base des pointeurs • Pointeur • Un pointeur est une variable qui contient l'adresse d'une autre variable. • En langage C, chaque pointeur est limité à un type de données. Il peut contenir l'adresse d'une variable simple de ce type ou l'adresse d'une composante d'un tableau de ce type. • Si un pointeur P contient l'adresse d'une variable A, on dit que 'P pointe sur A'. • Un pointeur est une variable qui peut 'pointer' sur différentes adresses. Le pointeur pouvant être affecté à différentes adresses. • Le nom d'une variable reste quant à lui toujours lié à la même adresse en RAM.
Notions de base des pointeurs • Opérateurs sur les pointeurs • &<var>: opérateur unaire qui retourne l’adresse de la variable var. int N; printf("Entrez un nombre entier : "); scanf("%d", &N); // scanf() prend une adresse comme deuxième argument • *<p>: opérateur unaire qui retourne le contenu pointer par p un pointeur. 1 int A=10, B; int *P; P = &A; 2 B = *P; 3 *P = 20; A P 10 &A A 1 20 3 B 10 2
Notions de base des pointeurs • Déclaration des pointeurs • <Type> *<Nom. Pointeur> : déclare un pointeur <Nom. Pointeur> qui être affecté des adresses de variables du type <Type> • Une déclaration comme: int *P ; • Le pointeur P est du type int *, donc P est un pointeur sur des objets int • P contient donc l'adresse d‘objet de type int • Lors de la déclaration d'un pointeur en C, ce pointeur est lié explicitement à un type de données. • Donc la variable pointeur P déclarée comme pointeur sur des int ne peut pas recevoir l'adresse d'une variable d'un autre type que int.
Notions de base des pointeurs • Opérations sur les pointeurs • Les opérateurs * et & ont la même priorité que les autres opérateurs unaires (la négation !, l'incrémentation ++, la décrémentation --). • Dans une même expression, les opérateurs unaires *, &, !, ++, -- sont évalués de droite à gauche. • Si un pointeur P pointe sur une variable X, alors *P peut être utilisé partout où on peut écrire explicitement X. • Si nous avons: P = &X; Y = X+1 // Y = *P + 1; X = X+10 // *P = *P + 10; X += 2 // *P +=2; ++X // ++(*P); ou ++*P; X++ // (*P)++
Notions de base des pointeurs • Valeur initiales • La valeur numérique 0 (zéro, NULL) est utilisée pour indiquer qu'un pointeur ne pointe 'nulle part‘, sur rien. int *P ; P = 0 ; • Les pointeurs sont aussi des variables et peuvent être utilisés comme telles. Soit P 1 et P 2 deux pointeurs sur des int, alors l'affectation P 1 = P 2; copie le contenu de P 2 vers P 1 pointe alors sur le même objet que P 2. Après les instructions suivantes : int A=20, B; // variable int. &A adresse de A int *P ; // P est un pointeur sur des int P = &A ; B = *P; // Contenu de A affecte a B
Notions de base des pointeurs • Exercise main() { int A = 1, B = 2, C = 3; int *P 1, *P 2; P 1=&A; // P 1 pointe sur A P 2=&C; // P 2 pointe sur C *P 1=(*P 2)++; // A = 3 C = 4 P 1=P 2; // P 1 pointe sur C P 2=&B; // P 2 pointe sur B *P 1 -=*P 2; // C = 2 ++*P 2; // B = 3 *P 1*=*P 2; // C = 6 A=++*P 2**P 1; // A = 24 P 1=&A; // P 1 pointe sur A *P 2=*P 1/=*P 2; // B = 6 return 0; }
Pointeurs et tableaux • int tableau[100]; • &tableau[0] et tableau sont une seule et même adresse. • Donc le nom d'un tableau est un pointeur constant sur le premier élément du tableau. int A[10], B; int *P ; P = A ; // P pointe sur A[0], P = &A[0]; equivalent B = *(P+1); // P+1 pointe sur le contenu de A[1] B = *(P+2); // P+2 pointe sur le contenu de A[2] . . . B= *(P+i); // P+i pointe sur le contenu de A[i]
Pointeurs et tableaux float A[20], float X ; float *P ; ………………… A[0] *(A) P = A ; // P pointe sur l’element A[0] X = *(P+9) ; // P+9 pointe sur l’element A[9] • A représente l'adresse de l’élément A[0], • *(A+1) pointe sur le contenu de A[1] • *(A+2) pointe sur le contenu de A[2] . . . • *(A+i) pointe sur le contenu de A[i] A[19] *(A+19)
Pointeurs et tableaux • Il existe une différence fondamentale entre une variable pointeur et le nom d'un tableau : – Un pointeur est une variable, sa valeur peut alors changée, des opérations arithmétiques sur ces pointeurs peuvent être effectuées, comme l’affectation P = A ou des incréments P++ ou toutes autres opérations arithmétiques. – Le nom associé à un tableau est une constante, donc des opérations arithmétiques comme A = P ou A++ sont illégales.
Pointeurs et tableaux • Exemple tableau VS pointeur main() { int T[10] = {-3, 4, 0, -7, 3, 8, 0, -1, 4, -9}; int POS[10]; // int * Tptr, *Pptr; int I, J; /* indices courants dans T et POS */ // Tptr = T; Pptr = POS; for (J=0, I=0; I<10; I++) if (T[I]>0) // (*(Tptr+I) > 0) { POS[J] = T[I]; // *(Pptr+J) = *(Tptr+I) J++; } return 0; }
Arithmétiques sur les pointeurs • Affectation d’un pointeur • Soient P 1 et P 2 deux pointeurs sur le même type de données, alors l'instruction P 1 = P 2 ; • fait pointer P 1 sur le même objet que P 2. • Addition et soustraction d’une valeur entière • Si le pointeur P pointe sur l'élément A[i] d'un tableau, alors P+n pointe sur A[i+n] et P-n pointe sur A[i-n]. • n correspond au nombre d’emplacements du type de donnée pointé qu’il faut se déplacer à partir de P pour atteindre l’emplacement recherché (P+n). • Ce déplacement (décalage) correspond à un saut de n*sizeof(type de donnée) octets dans la mémoire RAM. • Si P pointe sur des objets float, P+4 pointe alors sur le cinquième élément de type float, donc 16 octets à partir du début du vecteur de float pointé par P.
Arithmétiques sur les pointeurs • Incrément/Décrément d’un pointeur • Si P pointe sur l'élément A[i] d'un tableau, alors après l'instruction : – P = &A[i]; – P++ ; // P pointe sur A[i+1] – P = &A[i]; – P+= n ; // P pointe sur A[i+n] – P = &A[i]; – P-- ; // P pointe sur A[i-1] – P = &A[i]; – P-= n ; // P pointe sur A[i-n]
Arithmétiques sur les pointeurs • Rappels importants: • L'addition, la soustraction, l'incrémentation et la décrémentation sur les pointeurs sont seulement définies à l'intérieur d'un tableau. Si l'adresse formée par le pointeur et l'indice sort du domaine du tableau, alors le résultat n'est pas défini et peut causer des erreurs d’accès mémoire difficiles à détecter. • Ces opérations arithmétiques sont valables également pour les pointeurs qui pointent vers des variables indépendantes, i. e. , ne faisant pas partie d’un tableau. À titre d’exemple, si P pointe sur un élément de type quelconque, alors P+1 pointe sur l’octet qui suit immédiatement cet élément. Exemple : si P pointe sur un short int alors P+1 sera égale à l’adresse référencée par P plus 2 (puisque la taille d’un short int est 2 octets).
Arithmétiques sur les pointeurs • Exemples d’utilisations d’opérations arithmétiques int A[10] ; int *P ; P = A+9 ; // P pointe sur le dixieme element de A P = A+11 ; // P pointe au-dela du vecteur A de 8 octets P = A-1 ; // P pointe 4 octets avant le debut de A
Arithmétiques sur les pointeurs • Comparaisons de pointeurs (opérateurs relationnels) • On peut comparer deux pointeurs par <, >, <=, >=, ==, !=. • La comparaison de deux pointeurs qui pointent dans le même tableau est équivalente à la comparaison des indices correspondants. (Si les pointeurs ne pointent pas dans le même tableau, alors le résultat est donné par leurs positions relatives dans la mémoire).
Arithmétiques sur les pointeurs • Autre exemple int A[] = {12, 23, 34, 45, 56, 67, 78, 89, 90}; int *P, *P 2, B; P = A; B = *P+2; // B = 14 = A[0] + 2 B = *(P+2); // B = 36 = A[2] + 2 P 2 = &P+1; // P 2 pointe sur A[1] P 2 = &A[4]-3; // P 2 pointe sur A[1] P 2 = A+3 ; // P 2 pointe sur A[3] B = &A[7]-P; // B = 7 P 2 = P+(*P-10) ; // P 2 pointe sur A[2] B = *(P+8)-A[7]); // B = 23;
Pointeurs (chaînes de caractères) • Initialisation de pointeur sur des chaînes de caractères • Une chaîne de caractères est stockée dans un tableau linéaire de "char". La chaîne de caractères est complétée par le caractère NULL, le zéro binaire ('