pointeur

download pointeur

of 12

Transcript of pointeur

  • 8/9/2019 pointeur

    1/12

    INFOLANGUE

    9.2. Les pointeurs

    Dfinition: Pointeur

    Unpointeurest une variable spciale qui peut contenir

    l'adresse d'une autre variable.En C, chaque pointeur est limit un type de donnes. 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'.

    Remarque

    Les pointeurs et les noms de variables ont le mme rle: Ils donnent accs un emplacement

    dans la mmoire interne de l'ordinateur. Il faut quand mme bien faire la diffrence:

    * Unpointeurest une variable qui peut 'pointer' sur diffrentes adresses.

    * Le nom d'une variable reste toujours li la mme adresse.

    9.2.1. Les oprateurs de base

    Lors du travail avec des pointeurs, nous avons besoin

    - d'un oprateur 'adresse de': &

    pour obtenir l'adresse d'une variable.

    - d'un oprateur 'contenu de': *

    pour accder au contenu d'une adresse.

    - d'une syntaxe de dclaration

    pour pouvoir dclarer un pointeur.

    L'oprateur 'adresse de' : &

    &fournit l'adresse de la variable

    L'oprateur& nous est dj familier par la fonction scanf, qui a besoin de l'adresse de ses

    arguments pour pouvoir leur attribuer de nouvelles valeurs.

    Exemple

    int N;

    printf("Entrez un nombre entier : ");scanf("%d", &N);

  • 8/9/2019 pointeur

    2/12

    Attention !

    L'oprateur& peut seulement tre appliqu des objets qui se trouvent dans la mmoire

    interne, c.--d. des variables et des tableaux. Il ne peut pas tre appliqu des constantes ou

    des expressions.

    Reprsentation schmatique

    Soit P un pointeur non initialis

    et A une variable (du mme type) contenant la valeur 10 :

    Alors l'instruction

    P = &A;

    affecte l'adresse de la variable A la variable P. En mmoire, A et P se

    prsentent comme dans le graphique la fin du chapitre 9.1.2. Dans notre

    reprsentation schmatique, nous pouvons illustrer le fait que 'P pointe sur A' par

    une flche:

    L'oprateur 'contenu de' : *

    *dsigne le contenu de l'adresse rfrence par le pointeur

    Exemple

    Soit A une variable contenant la valeur 10, B une variable contenant la valeur 50 et P un

    pointeur non initialis:

  • 8/9/2019 pointeur

    3/12

    Aprs les instructions,

    P = &A;B = *P;*P = 20;

    - P pointe sur A,

    - le contenu de A (rfrenc par *P) est affect B, et

    - le contenu de A (rfrenc par *P) est mis 20.

    Dclaration d'un pointeur

    *dclare un pointeur qui peut recevoir des adresses de

    variables du type

    Une dclaration comme

    int *PNUM;

    peut tre interprte comme suit:

    "*PNUM est du type int"

    ou

    "PNUM est un pointeur surint"

    ou

    "PNUM peut contenir l'adresse d'une variabledu type int"

    Exemple

    Le programme complet effectuant les transformations de l'exemple ci-dessus peut se prsenter

    comme suit:

    |main()ou

    bien|main()

  • 8/9/2019 pointeur

    4/12

    |{ |{

    | /* dclarations */ |/* dclarations */

    | short A = 10; | short A, B, *P;

    | short B = 50; | /* traitement */

    | short *P; | A = 10;

    | /* traitement */ | B = 50;

    | P = &A; | P = &A;

    | B = *P; | B = *P;

    | *P = 20; | *P = 20;

    | return 0; | return 0;

    |} |}

    Remarque

    Lors de la dclaration d'un pointeur en C, ce pointeur est li explicitement un type de

    donnes. Ainsi, la variable PNUM dclare comme pointeur surint ne peut pas recevoir

    l'adresse d'une variable d'un autre type que int.

    Nous allons voir que la limitation d'un pointeur un type de variables n'limine pas seulement

    un grand nombre de sources d'erreurs trs dsagrables, mais permet une srie d'oprations

    trs pratiques sur les pointeurs (voir 9.3.2.).

    En travaillant avec des pointeurs, nous devons observer les rgles suivantes:

    Priorit de * et &

    * Les oprateurs * et & ont la mme priorit que les autres oprateurs unaires (la ngation !,

    l'incrmentation ++, la dcrmentation --). Dans une mme expression, les oprateurs unaires

    *, &, !, ++, -- sont valus de droite gauche.

    * Si un pointeur P pointe sur une variable X, alors *P peut tre utilis partout o on peut

    crire X.

    Exemple

    Aprs l'instruction

    P = &X;

    les expressions suivantes, sont quivalentes:

  • 8/9/2019 pointeur

    5/12

    Y = *P+1 Y = X+1

    *P = *P+10 X = X+10

    *P += 2 X += 2

    ++*P ++X

    (*P)++ X++

    Dans le dernier cas, les parenthses sont ncessaires:

    Comme les oprateurs unaires * et ++ sont valus de droite gauche, sans les

    parenthses lepointeurP serait incrment, non pas l'objetsur lequel P pointe.

    On peut uniquement affecter des adresses un pointeur.

    Le pointeur NUL

    Seule exception: La valeur numrique 0 (zro) est utilise pour indiquer qu'un pointeur nepointe 'nulle part'.

    int *P;

    P = 0;

    Finalement, les pointeurs sont aussi des variables et peuvent tre utiliss comme telles. Soit

    P1 et P2 deux pointeurs surint, alors l'affectation

    P1 = P2;

    copie le contenu de P2 vers P1. P1 pointe alors sur le mme objet que P2.

    Rsumons:

    Aprs les instructions:

    int A;int *P;P = &A;

    A dsigne le contenu

  • 8/9/2019 pointeur

    6/12

    de A

    &Adsigne l'adresse

    de A

    Pdsigne l'adresse

    de A

    *Pdsigne le contenu

    de A

    En outre:

    &P dsigne l'adresse du pointeur P

    *Aest illgal (puisque A n'est pas un

    pointeur)

    Exercice 9.1

    main(){

    int A = 1;

    int B = 2;int C = 3;int *P1, *P2;P1=&A;P2=&C;*P1=(*P2)++;P1=P2;P2=&B;*P1-=*P2;++*P2;*P1*=*P2;A=++*P2**P1;P1=&A;

    *P2=*P1/=*P2;return 0;

    }

    Copiez le tableau suivant et compltez-le pour chaque instruction du programme ci-dessus.

    AB C P1 P2

    Init. 1 2 3 / /

    P1=&A 1 2 3 &A /

  • 8/9/2019 pointeur

    7/12

    P2=&C

    *P1=(*P2)++

    P1=P2

    P2=&B

    *P1-=*P2

    ++*P2

    *P1*=*P2

    A=++*P2**P1

    P1=&A

    *P2=*P1/=*P2

    9.3.1. Adressage des composantes d'un tableau

    Exercice 9.2

    Comme nous l'avons dj constat au chapitre 7, le nom d'un tableau reprsente l'adresse de

    son premier lment. En d'autre termes:

    &tableau[0] et tableau

    sont une seule et mme adresse.

    En simplifiant, nous pouvons retenir que le nom d'un tableau est unpointeurconstantsur lepremier lment du tableau.

    Exemple

    En dclarant un tableau A de type int et un pointeur P surint,

    int A[10];int *P;

    l'instruction:

    P = A; est quivalente P = &A[0];

    http://www.ltam.lu/cours-c/prg-c96.htm#Heading204http://www.ltam.lu/cours-c/prg-c96.htm#Heading204
  • 8/9/2019 pointeur

    8/12

    Si P pointe sur une composante quelconque d'un tableau, alors P+1 pointe sur la

    composante suivante. Plus gnralement,

    P+ipointe sur la i-ime composante

    derrire P et

    P-ipointe sur la i-ime composante

    devant P.

    Ainsi, aprs l'instruction,

    P = A;

    le pointeur P pointe sur A[0], et

    *(P+1)dsigne le contenu

    de A[1]

    *(P+2)dsigne le contenu

    de A[2]

    ... ...

    *(P+i)dsigne le contenu

    de A[i]

    Remarque

    Au premier coup d'oeil, il est bien surprenant que P+i n'adresse pas le i-ime octetderrire P,

    mais la i-ime composante derrire P ...

    Ceci s'explique par la stratgie de programmation

    'dfensive' des crateurs du langage C:

    Si on travaille avec des pointeurs, les erreurs les plus

    perfides sont causes par des pointeurs malplacs et

    des adresses mal calcules. En C, le compilateur peut

    calculer automatiquement l'adresse de l'lment P+i

    en ajoutant P la grandeur d'une composante multiplie par i. Ceci est possible, parce que:

    - chaque pointeur est limit un seul type de donnes, et

    - le compilateur connat le nombre d'octets des diffrents types.

  • 8/9/2019 pointeur

    9/12

    Exemple

    Soit A un tableau contenant des lments du type float et P un pointeur surfloat:

    float A[20], X;float *P;

    Aprs les instructions,

    P = A;X = *(P+9);

    X contient la valeur du 10-ime lment de A, (c.--d. celle de A[9]). Une donne

    du type float ayant besoin de 4 octets, le compilateur obtient l'adresse P+9 en

    ajoutant 9 * 4 = 36 octets l'adresse dans P.

    Rassemblons les constatations ci dessus :

    Comme A reprsente l'adresse de A[0],

    *(A+1)dsigne le contenu

    de A[1]

    *(A+2)dsigne le contenu

    de A[2]

    ...

    *(A+i)dsigne le contenu

    de A[i]

    Attention !

    Il existe toujours une diffrence essentielle entre un pointeur et le nom d'un tableau:

    - Unpointeurest une variable,

    donc des oprations comme P = Aou P++ sont permises.

    - Le nom d'un tableau est une constante,

    donc des oprations commeA = P ouA++ sont impossibles.

    Ceci nous permet de jeter un petit coup d'oeil

    derrire les rideaux:

    Lors de la premire phase de la compilation, toutes

    les expressions de la forme A[i] sont traduites en

    *(A+i). En multipliant l'indice i par la grandeur d'une

    composante, on obtient un indice en octets:

    = *

  • 8/9/2019 pointeur

    10/12

    Cet indice est ajout l'adresse du premier lment du tableau pour obtenir l'adresse de la

    composante i du tableau. Pour le calcul d'une adresse donne par une adresse plus un indice

    en octets, on utilise un mode d'adressage spcial connu sous le nom 'adressage index':

    = +

    Presque tous les processeurs disposent de plusieurs registres spciaux (registres index) l'aide

    desquels on peut effectuer l'adressage index de faon trs efficace.

    Rsumons Soit un tableau A d'un type quelconque et i un indice pour les composantes de A,

    alors

    Adsigne l'adresse

    deA[0]

    A+idsigne l'adresse

    deA[i]

    *(A+i)dsigne le

    contenu deA[i]

    Si P = A, alors

    Ppointe sur

    l'lmentA[0]

    P+i pointe surl'lment

    A[i]

    *(P+i)dsigne le

    contenu deA[i]

    Formalisme tableau et formalisme pointeur

    A l'aide de ce bagage, il nous est facile de 'traduire' un programme crit l'aide du

    'formalisme tableau'dans un programme employant le 'formalisme pointeur'.

    Exemple

    Les deux programmes suivants copient les lments positifs d'un tableau T dans un deuxime

    tableau POS.

    Formalisme tableau

    main(){int T[10] = {-3, 4, 0, -7, 3, 8, 0, -1, 4, -9};int POS[10];

    int I,J; /* indices courants dans T et POS */for (J=0,I=0 ; I

  • 8/9/2019 pointeur

    11/12

    if (T[I]>0){POS[J] = T[I];J++;}

    return 0;

    }

    Nous pouvons remplacer systmatiquement la notation tableau[I] par*(tableau + I), ce

    qui conduit ce programme:

    Formalisme pointeur

    main(){int T[10] = {-3, 4, 0, -7, 3, 8, 0, -1, 4, -9};int POS[10];int I,J; /* indices courants dans T et POS */

    for (J=0,I=0 ; I0)

    {*(POS+J) = *(T+I);J++;}

    return 0;}

    Sources d'erreurs

    Un bon nombre d'erreurs lors de l'utilisation de C provient de la confusion entre soit contenu

    et adresse, soit pointeur et variable. Revoyons donc les trois types de dclarations que nousconnaissons jusqu'ici et rsumons les possibilits d'accs aux donnes qui se prsentent.

    Les variables et leur utilisationint A;

    dclare une variable simple du type int

    Adsigne le contenu

    de A

    &Adsigne l'adresse

    de A

    int B[];

    dclare un tableau d'lments du type int

    Bdsigne l'adresse de la premire

    composante de B.

    (Cette adresse est toujours constante)

    B[i]dsigne le contenu de la composante i

    du tableau

  • 8/9/2019 pointeur

    12/12

    &B[i]dsigne l'adresse de la composante i du

    tableau

    en utilisant le formalisme pointeur:

    B+idsigne l'adresse de la composante i du

    tableau

    *(B+i)dsigne le contenu de la composante i

    du tableau

    int *P;

    dclare un pointeursur des lments du type int.

    P peut pointersur des variables simples du type

    int ou

    sur les composantes d'un tableau du

    type int.

    P dsigne l'adresse contenue dans P

    (Cette adresse est variable)

    *P dsigne le contenu de l'adresse dansP

    Si P pointe dans un tableau, alors

    Pdsigne l'adresse de la premire

    composante

    P+idsigne l'adresse de la i-ime composante

    derrire P

    *(P+i)dsigne le contenu de la i-ime composante

    derrire P

    Exercice :

    Ecrire un programme qui lit deux tableaux A et B et leurs dimensions N et M au

    clavier et qui ajoute les lments de B la fin de A. Utiliser le formalisme

    pointeur chaque fois que cela est possible.