[Débutant en C] L'intérêt du pointeur.

15 sujets de 16 à 30 (sur un total de 44)

  • thellier

      #221957

      C’est vrai que si on a fait de l’assembleur on comprends VRAIMENT ce qu’on fait avec la mémoire
      Et puis ça vous influence… Ainsi je fais souvent
      RGB=&(RGB[3]); au lieu de RGB=RGB+3; pour passer à un pixel suivant

      mala04

        #221967

        Dire qu’on peut s’en passer, moi j’ai du mal à voir. Je ne connais aucun programme sérieux en C qui se passe de pointeurs. Cela fait parti du b.a.-ba du langage. Tableaux dynamiques, chaînage de listes, appels d’API, etc, autant dire qu’on va pas bien loin sans ça.

        Je me rappelle que mon prof de programmation en embarqué temps réel nous avait présenté la chose de manière imagée en considérant qu’un pointeur c’est « comme une boite à lettre »: on peut y mettre ce qu’on veut. Je n’ai jamais trop adhéré. Dans les faits, on ne pourrait y stocker qu’un seul « courrier » (une adresse mémoire) mais en fait c’est bien plus. C’est plutôt comme une « porte des étoiles » car au lieu d’un simple contenu c’est carrément un accès vers un espace mémoire  (un autre monde de l’Univers de notre programme pour faire filer la métaphore à la Stargate): structures, liste, tableau mono ou multi-dimensionnel des pixels d’une image, etc.

        En plus, si on reprend l’exemple de thellier, on peut même utiliser les pointeurs de manière à parcourir des tableaux entiers puisque chaque incrémentation de l’adresse du pointeur de notre tableau permet de passer à un élément suivant (pixel ou tout autre type de données). Et là, on touche quasiment l’assembleur en terme de logique et donc de perfs.

        Là où les pointeurs sont « dangereux » c’est qu’il n’y a pas de garde fou si on essaie d’accéder à une adresse hors limite (ex: au delà du nombre de pixels d’une image pour rester sur l’exemple de thellier). C’est pour ça que certains langages « bien pensant » ont essayé d’éradiquer la notion de  pointeur mais cela se fait au prix de performances très dégradées.

        Conseil de routard: toujours mettre ses pointeurs à NULL lorsqu’ils ne sont plus utiles (voire même dès l’init si ils ne sont pas utilisés de suite). Je dis ça, je dis rien mais c’est très utile lorsqu’on debug au pas à pas, ça limite les risques de violation d’accès et ça facilite le pistage des fuites mémoires. 😉

        thellier

          #221968

          >on peut même utiliser les pointeurs de manière à parcourir des tableaux

          Il faut dire que en C les tableaux SONT des pointeurs et eux non plus n’ont pas de garde fou …

          Alain

          modulo

            #221970

            En fait en C, il manque la référence et on n’a que les pointeurs (contrairement au c++).

            D’ailleurs ce n’est pas pour rien que l’opérateur «*» se nomme «opérateur de déréferencement».

            Le gros problème des pointeurs, ce sont les casts sauvages (conversion d’un type vers un autre type). D’autre part, l’arithmétique des pointeurs embrouille souvent le débutant, car une incrémentation d’un pointeur modifie le pointeur en ajoutant la taille de l’objet pointé, et non pas 1 octet. Ce qui conduit à des bugs folkloriques. On se fait même avoir quand on a l’habitude

            D’ailleurs j’ai souri en lisant ceci:

            RGB=&(RGB[3]); au lieu de RGB=RGB+3; pour passer à un pixel suivant

            Si RGB est une struct, ça risque de ne pas donner l’effet escompté 🙂

            Et je pense que RGB est une struct. À moins que ce ne soit un simple pointeur *char.

            Un programme pour l’auteur du premier post de ce thread, afin de bien montrer le risque de confusion:

            [code]

            #include<stdio.h>
            #include<malloc.h>

            int main(void)
            {
            typedef struct { char r; char g; char b; } RGB;
            RGB *rgb = malloc (1024);
            RGB *save_rgb = rgb;
            printf(« adresse de base rgb: %p\n », rgb);
            rgb++;
            printf(« adresse après incrémentation: %p\n », rgb);
            rgb+=3;
            printf(« adresse après addition de 3: %p\n », rgb);

            free(save_rgb);
            return 0;
            }

            [/code]

             

            En résumé, je dirais que les pointeurs c’est pourri, et qu’il vaut mieux limiter leur utilisation à du passage de paramètre quand on est obligé de faire du C et non du C++.

            Pour le reste, les algos de base sont déjà dans la Glib, alors pas la peine de réimplémenter ce qui est déjà fort bien fait (listes chainées, tableaux, queues…).

            Sauf si bien sûr on pense que «recoder une libc», c’est formateur.

            modulo

              #221973

              Et également, un tableau n’est PAS un pointeur en C !

              http://www.levenez.com/lang/c/faq/fclc007.html

               

              henes

                #221974

                La simple insertion d’un élément dans une liste chaînée de glib fait déréférencer 0 et crasher le programme dès qu’on manque de mémoire…
                Ce n’est que l’une des innombrables points qui font déconseiller l’utilisation de cette bibliothèque.

                Surtout que les listes exec fonctionnent parfaitement et que leur utilisation donne un code plus petit et plus rapide.
                Pas besoin d’importer toutes les m*rdes Unix sur Amiga…

                zouzou

                  #221987

                  Je constate qu’AI est rempli de programmeurs (on appelle çà désormais des développeurs il parait).

                  Je suis 100% pour l’apprentissage de la programmation par le C ou C++; mais je n’ai pas toujours raison. Comme d’autres ici, j’ai dans un premier tps appris en autodidacte dans mon adolescence, puis j’ai compris plus tard que je ne suis pas fait pour « coder » toute la journée, et encore moins pour pondre des schémas plus lourds que l’administration Française;)

                  Ca reste un hobby, donc un plaisir, et c’est suffisant ainsi.

                   

                  De l'Amiga et bien d'autres ici:

                  http://tutosproc.blogspot.fr/

                  huggyone76

                    #221988

                    L’apprentissage de la programmation par le C ou le C++ ça a ses avantages… et ses inconvénients !!!

                    Avec le recul, je me dis que la progression qu’on avait en DUT n’était pas si mal (il y a 20 ans…) : Pascal pour être proche de l’algorithme « pur » et donc proche de la logique des milliards de programmes qui tournent sur Terre, et assembleur (68000) pour savoir comment tout cela est compris par la machine (on appelait d’ailleurs ce cours « architecture des ordinateurs »). Et ensuite on a attaqué le C, puis le C++… et enfin après le DUT (mais là c’était plus pour le concept…), on a vu du Java (mouais…), du LISP (Lot of Insipid and Stupid Parenthesis pour ceux qui en ont souffert… 🙂 ) et… et c’est déjà pas mal ! 😀

                    En tout cas, pour moi l’algo et l’assembleur c’est un peu comme le solfège dans la musique. On peut faire sans, mais en faisant avec on aura de toute façon de meilleures bases pour la suite. A moins d’être un Dieu de la programmation (ou de la musique ! 😀 )… Sinon on se perd dans tout ce bordel !

                    A500+ACA500 - A600+Vampire 2+indivision ECS - A1200+Vampire V2 1200 - Mac Mini 1.42 sous MOS - Just CPC 128k - CPC 6128 - Atari STE 4Mo/CosmosEx - Atari Falcon CT60/SuperVidel 🙂
                    C64C + 1541-II + Lecteur K7 + SD - Sharp X68000 CZ-601C 4Mo + CF - Sharp X68000 CZ-611C 10Mo + CF + ext. MIDI

                    thellier

                      #221992

                      @modulo
                      Tu est d’une mauvaise fois AFFLIGEANTE
                      Je voulais souligner que les notations
                      RGB=&(RGB[3]); au lieu de RGB=RGB+3;
                      étaient équivalentes
                      Et tu sais elles restent équivalente qque soit la « taille » de RGB

                      >je pense que RGB est une struct. À moins que ce ne soit un simple pointeur *char.
                      Qui donc pourrait croire celà (que c’est une struct et non pas un char*) puisque je dis que je passe au pixel suivant de cette manière, en faisant +3, donc fatalement j’avais char *RGB;

                      >Et également, un tableau n’est PAS un pointeur en C !
                      >http://www.levenez.com/lang/c/faq/fclc007.html

                      Ta référence ne contient aucun argument valable il vaut mieux faire référence au « langage C » de Kerninghan et Ritchie pages 95 à 97
                      qui est bien moins tranché
                      « le nom d’un tableau est synonyme de l’adresse de son élément initial »
                      « En résumé,une expression comportant un tableau et un indice est équivalente à une autre écrite avec un pointeur et un déplacement »
                      Mais aussi à propos d’un tableau a
                      « un nom de tableau n’est pas une variable; donc des instructions telles a=pa; et a++ sont incorrectes »

                      Mais surtout je voulais surtout dire que les tableaux en C n’ont pas de garde fou non plus en ce sens ils sont aussi con que des pointeurs…
                      char tab[10];
                      int x;
                      x=100;
                      tab[x]=0; ==> bang

                      Alain

                      Alain

                      Tiki

                        #221997

                        Vous êtes grands !
                        Je ne comprends déjà plus rien.
                        Enfin, pour l’instant.
                        Par contre, ce que je crois avoir compris, c’est que sur nos systèmes, il est préférable d’initialiser un pointeur à une adresse avant son utilisation. Sinon…. Ca plante. Je me trompe ?

                        Tiki

                        Anonyme

                          #221998

                          Haha, oué, tu m’étonnes 😀
                          si t’envoie ton code vers une adresse aléatoire, au moyen d’un pointeur non initialisé, le comportement de ton programme sera totalement imprévisible (allant de « ça plante à tout les coups » à « je comprends pas, pourtant ça marche chez moi »).

                          D’autant que l’Amiga est quand même super tolérant avec les dérapages mémoires. Faudra pas compter sur lui pour te signaler les sorties de l’espace mémoire de ton process (mais des outils existent pour remédier à ça).

                          zzd10h

                            #221999

                            « mais des outils existent pour remédier à ça). »

                            Oui, le reboot 🙂

                            Anonyme

                              #222001

                              Hialmar

                                #222038

                                J’enseigne le C à Toulouse donc je vais essayer de faire un résumé de ce que j’explique à mes étudiants.

                                Les passages de paramètres à un sous-programme en C ne marchent que par valeur.

                                C’est à dire qu’on recopie la valeur du paramètre effectif (ce qui est passé en paramètre quand tu appelle une fonction) dans le paramètre formel (la variable qui est utilisée dans la fonction).

                                Du coup, la seule solution pour modifier une variable dans une fonction est de passer son adresse en paramètre et de la manipuler avec une variable pointeur.

                                Pourquoi ne pas travailler directement sur la variable ?

                                Ceci n’est possible que si la variable est globale et dans ce cas le sous-programme ne servira qu’à modifier cette variable.

                                Or quand on écrit un sous-programme le but c’est qu’il puisse travailler avec n’importe qu’elle variable.

                                Sans pointeur :

                                int x; int y;

                                void fonction() {

                                x = x + 1;

                                }

                                void main() {

                                x = 1; y = 6;

                                fonction();

                                }

                                Ici la fonction ne peut ajouter 1 qu’à la variable x. Si je veux faire pareil sur la variable y il faut créer une autre fonction 🙁

                                Avec pointeur :

                                void fonction(int *p) {

                                *p = *p + 1;

                                }

                                void main() {

                                int x, y;

                                x=1; y=6;

                                fonction(&x); fonction(&y);

                                }

                                Ici lors du premier appel j’ajoute 1 à la variable x et la seconde fois j’ajoute 1 à la variable y. Ma fonction marche pour n’importe qu’elle variable entière.

                                Ce qui se passe : quand j’appelle la fonction je donne la valeur de l’adresse de la variable x (c’est à dire l’endroit où on stocke les données en mémoire). La variable pointeur p va donc contenir cette adresse. Quand je fais *p je manipule l’espace mémoire qui se trouve à l’adresse contenue dans p. Et donc *p vaut la valeur contenue à cet endroit en mémoire (qui correspond à l’endroit en mémoire de la variable x). Quand je fais *p = XXX; j’écris une nouvelle valeur à cet endroit en mémoire et donc je modifie le contenu de la variable x.

                                Bon bien sûr il y a plein de détails en plus. La taille de la zone mémoire manipulée dépend du type. Ici int correspond (en général) à 4 octets en mémoire. Donc quand je fais *p = XXX; je modifie en fait 4 octets en mémoire à partir de l’adresse contenue dans p.

                                Enfin dernier exemple de ce qui ne marche pas :

                                void fonction(int p) {

                                p = p + 1;

                                }

                                void main() {

                                int x, y;

                                x=1; y=6;

                                fonction(x);

                                }

                                Ici la variable p (le paramètre formel) reçoit la valeur de la variable x, puis la variable p est modifiée mais pas la variable x. Donc ça ne fait pas ce qu’on veut (augmenter de un la variable passée en paramètre effectif).

                                --
                                Patrice aka Hialmar
                                A500+/A600+aca620/A1200+aca1233
                                Membre de Silicium

                                zouzou

                                  #222100

                                  hialmar, tu enseignes dans quelle formation?

                                  De l'Amiga et bien d'autres ici:

                                  http://tutosproc.blogspot.fr/

                                15 sujets de 16 à 30 (sur un total de 44)

                                • Vous devez être connecté pour répondre à ce sujet.

                                Forums AmigaOS, MorphOS et AROS Développement [Débutant en C] L'intérêt du pointeur.

                                Amiga Impact