IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Affichage d'une adresse mémoire.


Sujet :

C

  1. #1
    Membre averti
    Inscrit en
    Février 2011
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 12
    Par défaut Affichage d'une adresse mémoire.
    Bonjour,

    J'aimerais que quelqu'un m'éclaircisse sur un point.
    J'ai lu dans un tuto que l'adresse d'une variable s'affiche via ("%p",&variable). alors qu'il est dit (toujours dans ce tuto) d'utiliser ("%d", pointeur) pour afficher la valeur d'un pointeur.

    J'ai essayé et si je fais par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int age = 10; // variable
        int *ptage = &age; //le pointeur ptage reçoit l'adresse de age
     
        printf("Valeur du pointeur age %d\n", ptage); //renvoie une valeur décimale
        printf("adresse mémoire de la variable age %p\n",&age);" //renvoie une valeur hexadécimale
    Les printf devraient m'envoyer les mêmes valeurs, or ce n'est pas le cas !

    Par contre, si je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int age = 10;
        int *ptage = &age;
     
        printf("Valeur du pointeur age %p\n", ptage);
        printf("adresse mémoire de la variable age %p\n",&age);
    Les 2 valeurs sont identiques et hexadécimales.

    Je commence seulement avec ce langage et je remercie par avance celui qui pourra m'expliquer.

  2. #2
    Membre chevronné
    Inscrit en
    Décembre 2010
    Messages
    290
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 290
    Par défaut
    Le format "%d" est fait pour afficher une variable de type "int".
    Le format "%p" est fait pour afficher une variable de type "pointeur".

    Il se trouve que sur beaucoup d'architectures (mais pas toutes), les deux types sont identiques : il s'agit de variables entières sur 32 bits.
    Mais dans un souçi de portabilité, le C ANSI a définit les deux formats de façon différente.
    Il faut noter que représenter un pointeur ne signifie pas forcément représenter une valeur numérique brute. Sur certaines plateformes, on pourrait vouloir le représenter sous une forme plus sympathique pour l'utilisateur, comme "SEGMENT:OFFSET" ou une autre construction.
    Ici, dans le cas %p, il se trouve qu'on va préférer l'afficher sous la forme hexadécimale. Mais la valeur hexa devrait être identique à sa valeur décimale affichée avec %d.

  3. #3
    Membre averti
    Inscrit en
    Février 2011
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2011
    Messages : 12
    Par défaut
    Merci,

    Donc si j'ai bien compris,

    *ptage = &age;
    printf("Valeur du pointeur age %d\n", ptage) n'affichera pas la même valeur que printf("adresse mémoire de la variable age %p\n",&age) car ils considérés comme 2 types différents. Néanmoins, les valeurs seront équivaux.

    Je vais faire la conversion entre ces 2 résultats pour voir.

    Autre question si possible, j'aimerai savoir si le code ci-dessous me permet d'afficher l'ensemble des adresses d'un tableau :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int tableau[5] = {0,1,2,3,4};
    
    int i = 0;
    int somme = 0;
    for (i = 0; i<6; i++)
    {
        printf("Adresse %d : %d \n",i, (tableau + i));
        somme += tableau[i];
    
    }
    printf("%d\n", somme);
    Car les résultats vont de 4 en 4 et il est dit (toujours dans ce tuto), que les adresses d'un tableau doivent se suivre.

    Cdt,

  4. #4
    Membre Expert
    Avatar de kwariz
    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Octobre 2011
    Messages
    898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2011
    Messages : 898
    Par défaut
    Citation Envoyé par Zerphe39 Voir le message
    Merci,

    Donc si j'ai bien compris,

    *ptage = &age;
    printf("Valeur du pointeur age %d\n", ptage) n'affichera pas la même valeur que printf("adresse mémoire de la variable age %p\n",&age) car ils considérés comme 2 types différents. Néanmoins, les valeurs seront équivaux.

    Je vais faire la conversion entre ces 2 résultats pour voir.
    Bonjour,
    Attention, il faut un ptage=&age. Il faut impérativement utiliser %p pour afficher une adresse car suivant ta plateforme (linux/windows/mac en 32 ou 64bit) et ton compilateur (ms, gcc, icc, ...) la taille d'un int peut être différente de la taille d'un pointeur. Si tes int sont 32bits et ton adressage à 64bits la valeur décimale affichée sera tronquée.

    Citation Envoyé par Zerphe39 Voir le message
    Autre question si possible, j'aimerai savoir si le code ci-dessous me permet d'afficher l'ensemble des adresses d'un tableau :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int tableau[5] = {0,1,2,3,4};
     
    int i = 0;
    int somme = 0;
    for (i = 0; i<6; i++)
    {
        <gras>printf("Adresse %d : %d \n",i, (tableau + i));</gras>
        somme += tableau[i];
     
    }
    printf("%d\n", somme);
    Car les résultats vont de 4 en 4 et il est dit (toujours dans ce tuto), que les adresses d'un tableau doivent se suivre.

    Cdt,
    Les résultats vont de 4 en 4 car stocker un int prend (sur ta plateforme avec ton compilateur) 4 octets (=32bits) : les adresses sont bien consécutives. N'oublies pas de trabsformer le <6 avec un <5 ... sinon tu dépasses les limites de ton tableau ...

  5. #5
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par défaut
    Bonjour,
    • %d est généralement une mauvaise idée pour afficher un pointeur, surtout sur des systèmes où la représentation hexadécimale d'une adresse a sa signification (comme le vieux DOS, ou certains cas d'allocation mémoire dans un OS moderne).
    • Si tu ne sais pas particulièrement ce que tu fais, utilise %p.
    • Si tu veux forcer une représentation particulière et que tu sais ce que tu fais (taille etc.), tu peux utiliser %x ou %X avec des valeurs de taille (%lx, %llx, %zx en C99, %Ix sous Windows, etc ou de justification dépendant de la plate-forme.

    À noter aussi que sous certains systèmes, les pointeurs de différents types peuvent avoir différentes tailles ou différents formats internes; selon le standard C, le comportement de printf() n'est pas défini si tu ne castes pas le pointeur en (void*) ou (const void*) lors du passage à printf().

    Ce qui nous donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #define TAILLE 5
    int tableau[TAILLE] = {0,1,2,3,4};
     
    int i = 0;
    int somme = 0;
    for (i = 0; i<=TAILLE; i++) /*Inférieur ou égal si on veut l'adresse de fin en plus.*/
    {
        void const *pcv = (tableau + i);
        printf("Adresse %d : %p", i, pcv);
        if(i < TAILLE) /*Strictement inférieur, ici*/
        {
            printf(" = %d\n", tableau[i]);
            somme += tableau[i];
        }
        else
            printf("%s", " (on est sorti du tableau)\n");
    }
    printf("Somme: %d\n", somme);
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Membre émérite
    Avatar de Kirilenko
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    234
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 234
    Par défaut
    Sémantiquement, un pointeur n'est pas un entier. Ils désignent tous deux des entités différentes : l'un une adresse mémoire, l'autre des valeurs de types entières. Or, si on fait confiance au typage, mélanger ces deux abstractions serait une mauvaise idée.

    Concrètement, c'est une mauvaise idée, car tu risques de tomber sur de la perte d'information. Suivant le modèle de donnée de ton implémentation, la taille d'un pointeur peut être plus importante que celle d'un int (I16LP32, LLP64, *LP64 entre autres). Du coup, ce n'est pas une très bonne idée d'utiliser le format %d pour afficher des pointeurs.

    Formellement, si on parle norme, ça se complique encore plus. Tout d'abord, tous les pointeurs n'ont pas forcément la même taille (sous DOS p.ex.), ce qui nécessite un transtypage dans l'appel de printf.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <stdio.h>
    #include <stdlib.h>
     
    int 
    main (void)
    {
      int n;
      printf ("%p\n", (void *)&n);
      return EXIT_SUCCESS;
    }
    Si tu veux utiliser un type entier pour faire ces manipulations, il existe le type intégral intptr_t (C99).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <inttypes.h>
    #include <stdio.h>
    #include <stdlib.h>
     
    int 
    main (void)
    {
      int n;
      printf ("%" PRIxPTR "\n", (uintptr_t)(void *)&n);
      return EXIT_SUCCESS;
    }
    Récursivité en C : épidémie ou hérésie ?

    "Pour être un saint dans l'Église de l'Emacs, il faut vivre une vie pure. Il faut se passer de tout logiciel propriétaire. Heureusement, être célibataire n'est pas obligé. C'est donc bien mieux que les autres églises" - Richard Stallman

Discussions similaires

  1. Comment modifier la valeur d'une adresse mémoire ?
    Par copterkill dans le forum Windows
    Réponses: 6
    Dernier message: 08/02/2009, 22h18
  2. Réponses: 5
    Dernier message: 27/05/2008, 06h06
  3. lire le contenu d'une adresse mémoire avec VB Script
    Par pierre.zelb dans le forum VBScript
    Réponses: 2
    Dernier message: 13/12/2006, 13h32
  4. lire la valeur d'une adresse mémoire
    Par ilimo dans le forum Windows
    Réponses: 17
    Dernier message: 11/04/2006, 15h21
  5. Réponses: 6
    Dernier message: 19/09/2005, 19h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo