Partage
  • Partager sur Facebook
  • Partager sur Twitter

pointeurs (petit incompréhension)

Sujet résolu
    27 janvier 2024 à 4:03:00

    Bonjour ,
    Je pense que je n'ai pas bien compris , mais je pose la question quand même . Pas Taper svp.
    voila ,
    "créez-et-initialisez-des-pointeurs" la première leçon sur les pointeurs.
    Je rencontre un soucis dans le cours comme dans le livre ; il est indiqué comme exemple :
    int age = 10;
    int *pointeurSurAge = &age;
     
    printf("%d", pointeurSurAge);
     
     
    //le printf doit renvoyer :
     
    177450 //sensé si je comprend être l'adresse de la variable age
    hors je test sur mon ordinateur et les résultat a cette manipulation me donne des résultats qui n'ont rien a voir avec du Hexadécimal. La seul solution pour palier a cela est d'indiquer %p au lieu du %d comme mentionné dans le cours.
    #include <stdio.h>
    #include <stdlib.h>
     
    int main(int argc,char*argv[])
     
    {
     
    int variable = 10;
     
    printf("Valeur Variable = %d\n",variable);
     
    printf("Adress Variable =%p\n",&variable);
     
    int *pointeur;
     
    pointeur = &variable;
     
     
    printf ("Adress de la variable du pointeur est %p\n",pointeur);
    printf ("valeur contenu dans le pointeur est %d\n",*pointeur);
     
     
        return 0;
    }
    
    Je suis navrés si ma question est idiote :euh:
    • Partager sur Facebook
    • Partager sur Twitter
      27 janvier 2024 à 9:55:58

      Bonjour,

      Je suis navrés si ma question est idiote

      Quelle est votre question ?

      • Partager sur Facebook
      • Partager sur Twitter

      Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
      La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

        27 janvier 2024 à 11:56:20

        Pour afficher une adresse on utilise bien %p (%p affiche en hexadécimale).

        %d sert à afficher des entiers (int) en décimale (pas en hexadécimale). Il ne devrait pas servir à afficher des adresses.

        • Partager sur Facebook
        • Partager sur Twitter
        ...
          27 janvier 2024 à 14:56:35

          Qui plus est, on est censé convertir l'adresse en void*

          printf ("adresse = %p\n", (void *) &ma_variable);

          parce que les pointeurs ne sont pas forcément tous de la même taille pour une architecture particulière .... (exemple = adresses dans la Ram / dans une Eprom sur un microcontroleur ; ou far/near pointeurs du bon vieux temps du 8086 (?))

          -
          Edité par michelbillaud 27 janvier 2024 à 15:00:36

          • Partager sur Facebook
          • Partager sur Twitter
            27 janvier 2024 à 18:46:50

            Il faut ajouter que l'adresse obtenue dépendra de l'architecture de l'ordinateur, du système d'exploitation, et probablement de la version du compilateur.
            • Partager sur Facebook
            • Partager sur Twitter

            Le Tout est souvent plus grand que la somme de ses parties.

              28 janvier 2024 à 2:36:34

              Bonjour ,

              Merci pour vos réponses ;

              Donc sur la page 148 du livre comme dans le cours en ligne ; il y a bien une coquille.

              	
              printf ("adresse = %p\n", (void *) &ma_variable);

              Merci pour cette information je n'est pas encore abordé cela :D. Je débute tout juste le cours.

              • Partager sur Facebook
              • Partager sur Twitter
                28 janvier 2024 à 8:15:28

                Une coquille c'est une faute typographique, là c'est autre chose. Un oubli, volontaire ou pas, ou une erreur. L'auteur du cours

                • Soit a choisi délibérément de faire une entorse à la norme pour éviter d'avoir à justifier la conversion explicite avec les histoires d'adresses de tailles différentes qui compliquent ;
                • Soit a oublié, et n'a pas vérifié ses exemples en les compilant avec un maximum d'avertissements
                • Soit ne connaît pas ce point (emmerdant) du langage C, ce qui ne l'empêche pas de faire des cours, comme si.

                En pratique, ne pas convertir avec (void*), ca passe quand même (Ce n'est pas une erreur qui bloque la compilation et ca s’exécute),  la plupart du temps, si on programme sur un pc (avec les pointeurs de la même taille), ce qui est la situation d'apprentissage la plus probable.

                Dans le premier cas, il aurait fallu une petite note disant qu'en fait il faudrait écrire ceci cela, et qu'on verra plus tard pourquoi. Histoire que le débutant ne soit pas dérouté si il voit  des avertissements en compilant.

                ---

                On retrouve ce problème quand on doit passer un pointeur nul à certaines macros ou fonctions (j'ai oublié lesquelles, ça me reviendra peut être) : il faut mettre  (void*) 0, au lieu de 0 tout court, parce que les pointeurs ne sont pas forcement de la même taille que les entiers, contrairement à ce qui se passait en C préhistorique (à l'époque, le type void* n'existait pas).

                --- Compléments

                - si on écrit

                	printf("Adresse = %p\n", 0);

                on se fait engueuler gentiment (si on a mis les options pour avoir les warnings)

                 gcc -std=c2x -Wall -Wextra a.c
                a.c: In function ‘main’:
                a.c:7:28: warning: format ‘%p’ expects argument of type ‘void *’, but argument 2 has type ‘int’ [-Wformat=]
                    7 |         printf("Adresse = %p\n", 0);
                      |                           ~^     ~
                      |                            |     |
                      |                            |     int
                      |                            void *
                      |                           %d
                

                - mais pas avec

                	printf("Adresse = %p\n", & variable);

                même si on devrait

                https://copyprogramming.com/howto/printf-p-and-casting-to-void#why-is-a-pointer-cast-as-voidp-when-used-in-printf-duplicate

                L'explication (du fait qu'on devrait), c'est lié aux fonctions variadiques (qui ont des paramètres en nombre variable et de types différent).  Pour qu'une telle fonction puisse accéder aux paramètres qui lui ont été envoyés, il faut qu'elle en connaisse le type... Et pour garantir que ce qu'on a passé est d'un type compatible, on s'arrange pour avoir le type (void *) qui est compatible avec tout le monde.

                ---

                > @pierrot l'adresse obtenue dépendra de l'architecture de l'ordinateur, du système d'exploitation, et probablement de la version du compilateur.

                Et ça peut même varier à chaque exécution

                Avec

                #include <stdio.h>
                  
                int main()
                {
                	int variable = 10;
                	printf("Valeur  = %d\n",            variable);
                	printf("Adresse = %p\n", (void *) & variable);
                    return 0;
                }

                Compilation et exécutionS

                $ gcc     a.c   -o a
                $ ./a
                Valeur  = 10
                Adresse = 0x7ffe66e354ec
                $ ./a
                Valeur  = 10
                Adresse = 0x7ffe125f1fcc
                $ ./a
                Valeur  = 10
                Adresse = 0x7ffd5d41b33c
                

                Explication :  la pile des appels (dans laquelle se trouvera la variable) n'est pas installée au même endroit de l'espace mémoire à chaque exécution, pour compliquer la vie des malfaisants. Sa position est aléatoire, c'est l'ASLR (address space layout randomization)

                https://stackoverflow.com/questions/3699845/how-is-it-that-main-function-is-always-loaded-at-the-same-address-whereas-variab



                -
                Edité par michelbillaud 28 janvier 2024 à 13:18:56

                • Partager sur Facebook
                • Partager sur Twitter
                  29 janvier 2024 à 0:27:56

                  Merci michelbillaud.

                  Pour ces compléments d'informations.

                  :)

                  J'avoue avoir imprimé ta réponse afin de voir par la suite si j'arrive a comprendre la totalité de ces explications. Comme je disait , je débute totalement et il y a 1 semaine je ne savais même pas ce qu'était un pointeur.

                  Merci Beaucoup.

                  nrk.

                  • Partager sur Facebook
                  • Partager sur Twitter
                    30 janvier 2024 à 23:03:03

                    Personne n'a la science infuse, ça s'apprend et pour ça il faut bien commencer (et c'est pas dit qu'un jour on s'arrêtera d'apprendre)

                    La difficulté, c'est pas de savoir ce qu'est un pointeur (une donnée qui peut contenir l'adresse d'un truc), mais comment s'en servir pour faire des choses (et correctement : efficacement, pas de fuite mémoire, pas de double libération, pas d'adresses invalides etc)

                    -
                    Edité par michelbillaud 30 janvier 2024 à 23:05:40

                    • Partager sur Facebook
                    • Partager sur Twitter

                    pointeurs (petit incompréhension)

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    • Editeur
                    • Markdown