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

SDL Discussion :

Plantage fenetre SDL (rebond d'un carré sur les parrois de l'écran)


Sujet :

SDL

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut Plantage fenetre SDL (rebond d'un carré sur les parrois de l'écran)
    Bonsoir j'ai fait un programme qui fait rebondir un carré dans la fenêtre SDL tous ce passe bien pendant un peut prêt 10 second ensuite le programme plante. Ce qui est bizarre c'est que si j'utilise GDB pour voir d'où vien le problème et bien lui n'en détecte pas et le programme s'éxècute sans problème jusqu'à la fin.

    Pourriez-vous m'aider car je ne vois pas d'où vient le problème.

    Merci par avance.

    Voici mon code :

    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
     
     
     
    #include <stdlib.h>
    #include <stdio.h>
    #include <assert.h>
    #include <SDL.h> /*Si sa ne marche pas essayer SDL/SDL.h*/
     
    #define WIN_W 320
    #define WIN_H 240
    #define BPP 32
    #define FLAGS SDL_HWSURFACE|SDL_DOUBLEBUF
     
    #define TRUE 1
    #define FALSE 0
     
    typedef char boul;
    typedef unsigned int color;
     
    /*Création du sprite*/
     
    typedef struct _sprite *sprite;
    struct _sprite
    {
      int w;
      int h;
      SDL_Rect pos;
      SDL_Surface *surface;
    };
     
    /* Fonction d'initialisation de la fenêtre SDL*/
     
    SDL_Surface *init_sdl()
    {
      SDL_Surface *screen=NULL;
      if(SDL_Init (SDL_INIT_VIDEO)==-1)
        {
          fprintf(stderr,"init not SDL : %s\n",SDL_GetError());
          exit(EXIT_FAILURE);
        }
      atexit(SDL_Quit);
     
      screen=SDL_SetVideoMode(WIN_W, WIN_H, BPP, FLAGS);
     
      if(screen == NULL)
        {
          fprintf(stderr,"Error display Window : %s\n",SDL_GetError());
          exit(EXIT_FAILURE);
    	}
      SDL_WM_SetCaption  ("Collision",NULL);
     
      return screen;
    }
     
    /*Libération de la mémoire pour les surfaces*/
     
    void My_SDL_FreeSurface(SDL_Surface *I)
    {
      SDL_FreeSurface(I);
    }
     
    /*Création des sprite*/
    sprite sprite_create(int w, int h, int x, int y,int a,int b, int c)
    {
      sprite I=(sprite)malloc(sizeof(struct _sprite));
      I->w=w;
      I->h=h;
      I->pos.x=x;
      I->pos.y=y;
      I->surface=NULL;
      I->surface=SDL_CreateRGBSurface(SDL_HWSURFACE,I->w,I->h,32,0,0,0,0);
      SDL_FillRect(I->surface,NULL,SDL_MapRGB(I->surface->format,a,b,c));
      return I;
    }
     
    /*Liberation de la mémoire pour les sprites*/
     
    void sprite_destroy(sprite I)
    {
      My_SDL_FreeSurface(I->surface);
      free(I);
    }
     
    /*La boucle des événement*/
     
    void loop_event()
    {
      SDL_Event event;
      boul stop = TRUE;
     
      do
        {
          while(SDL_PollEvent(&event))
    	{
    	  if(event.type==SDL_QUIT ||(
    	     event.button.button==SDL_BUTTON_RIGHT && event.type==SDL_MOUSEBUTTONUP))
    	    stop=FALSE;
    	}
        }while(stop);
    }
     
     
    int main(int argc, char *argv[])
    {
      SDL_Surface *screen;
      sprite rectwhite;
      int i=5000;
      int vx=1, vy=1;
     
      screen=init_sdl();
     
      rectwhite=sprite_create(10,10,50,50,255,255,255);
     
             while(i>0)
    	    {
    	      rectwhite->pos.x+=vx;
    	      rectwhite->pos.y+=vy;
    	      if(rectwhite->pos.x<=0 && vx<0)
    		vx=-vx;
    	      if(rectwhite->pos.x+rectwhite->w>=320 && vx>0)
    		vx=-vx;
    	      if(rectwhite->pos.y<0 && vy<0)
    		vy=-vy;
    	      if(rectwhite->pos.y+rectwhite->h>=240 && vy>0)
    		vy=-vy;
    	      SDL_BlitSurface(rectwhite->surface,NULL,screen,&(rectwhite->pos));
    	      SDL_Flip(screen);
    	      SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0,0,0));
    	      SDL_Delay(5);
                  i--;
                  printf("i == %d \n", i);
    	      }
     
    	   loop_event();
     
      sprite_destroy(rectwhite);
      My_SDL_FreeSurface(screen);
     
      if(argc<-1) printf(argv[0]);
        return EXIT_SUCCESS;
    }

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 218 582
    Points
    218 582
    Billets dans le blog
    120
    Par défaut
    Bonjour,

    Chez moi, cela n'a pas planté. Par contre, à la fin du programme, il ne faut pas libérer la surface correspondant à l'écran ->
    The surface returned is freed by SDL_Quit() and should nt be freed by the caller.
    Ceci est très mauvais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef struct _sprite *sprite;
    Vous cachez un pointeur en faisant cela. Cacher un pointeur est mauvais, car vous pouvez oublier que c'est un pointeur (utiliser . à la place de -> ce qui provoque des erreurs de compilation (ouf)), mais aussi, oublier de libérer la mémoire.

    Vous devriez faire attention à l'indentation.

    Par contre, impossible de quitter le programme tant que la boucle n'est pas terminée.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut
    Merci pour ton aide et tes conseils , hier soir j'ai mis en veille mon ordi et quand je l'ai rallumé ce matin sa marché sans problème.

    Merci pour le sdl_quit je ne savait pas.

    Pour l'indentation qu'est-ce que je devrais amélioré dans le codes.

    En ce qui concerne : typedef struct _sprite *sprite;

    je fait comme ça car sur les cours vidéo youtube de jacque Olivier lapyere qui a un bac +5 il dit de faire comme ça c'est pour éviter d'avoir à rappeler plusieurs fois la struct.

  4. #4
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    26 860
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 26 860
    Points : 218 582
    Points
    218 582
    Billets dans le blog
    120
    Par défaut
    je fait comme ça car sur les cours vidéo youtube de jacque Olivier lapyere qui a un bac +5 il dit de faire comme ça c'est pour éviter d'avoir à rappeler plusieurs fois la struct.
    Le problème n'est absolument pas le typedef struct qui est utile pour, comme vous l'avez dit, éviter d'appeler plusieurs fois struct. Le problème est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef struct _sprite *sprite;
    Ce code indique que un sprite est en réalité un _sprite*. L'étoile indique que c'est un pointeur, par contre, dans le nom/type sprite, cette indication est perdue. Pour un programmeur, un sprite n'a aucune raison d'être un pointeur et, sémantiquement, un sprite (sous le nom de sprite) n'est pas un pointeur.
    Bref, vous cachez un pointeur. Cela veut dire qu'une copie de ce style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    sprite s = malloc(...); // c'est un pointeur :'(
    sprite s2 = s;
    // Le fait que l'on ne voit pas que c'est un pointeur, on peux allégrement oublier le free()
    // le fait que ce sont des pointeurs, peuvent nous tromper sur le fait que s2 pointe sur le même sprite que s ...
    Même si vous, aujourd'hui, vous savez que c'est un pointeur, demain (ou plus tard) vous allez relire le code et oublier.
    Les gens qui vous lisent, risque de passer à côté de cela.

    En résumé, cela rend la lecture du code difficile (et le code n'est jamais lu que par soit même surtout si on demande de l'aide sur les forums) et cela peut provoquer des erreurs.

    Pour l'indentation, c'est aussi une question de rendre le code plus lisible.
    À chaque fois que l'on utilise '{' il faut que le code dans le bloc, soit indenté, pour que visuellement, on comprenne rapidement que le code est dans le bloc.
    Le bloc se termine avec '}' qui doit se trouver sur la même colonne que le '{' qui a ouvert le bloc.

    Ce code :
    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
    19
    while(i>0)
    {
      rectwhite->pos.x+=vx;
      rectwhite->pos.y+=vy;
      if(rectwhite->pos.x<=0 && vx<0)
    vx=-vx;
      if(rectwhite->pos.x+rectwhite->w>=320 && vx>0)
    vx=-vx;
      if(rectwhite->pos.y<0 && vy<0)
    vy=-vy;
      if(rectwhite->pos.y+rectwhite->h>=240 && vy>0)
    vy=-vy;
      SDL_BlitSurface(rectwhite->surface,NULL,screen,&(rectwhite->pos));
      SDL_Flip(screen);
      SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0,0,0));
      SDL_Delay(5);
    	  i--;
    	  printf("i == %d \n", i);
      }
    Devient donc :
    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
    19
    20
    21
    while(i>0)
    {
    	rectwhite->pos.x+=vx;
    	rectwhite->pos.y+=vy;
    	if(rectwhite->pos.x<=0 && vx<0)
    		vx=-vx;
    	if(rectwhite->pos.x+rectwhite->w>=320 && vx>0)
    		vx=-vx;
    	if(rectwhite->pos.y<0 && vy<0)
    		vy=-vy;
    	if(rectwhite->pos.y+rectwhite->h>=240 && vy>0)
    		vy=-vy;
     
    	SDL_BlitSurface(rectwhite->surface,NULL,screen,&(rectwhite->pos));
    	SDL_Flip(screen);
    	SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0,0,0));
    	SDL_Delay(5);
     
    	i--;
    	printf("i == %d \n", i);
    }
    Surtout que c'est ultra important, car vous utilisez des if à une ligne.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut
    Ok j'ai compris ce que tu veux dire pour le le nommage des pointeur.

    Merci pour tes réponses et tes conseilles à plus.

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut
    Oui mais jacque olivier lapeyre expliquait qu'on faisait un typedef struct _nom *nom par exemple pour ne pas à avoir a rappeler la struct a chaque fois.
    Si on ne doit pas faire comme ça et donc éviter de passer par un pointeur comment fait-on alors quand on à une struct dont on doit se servir de très nombreuse fois le but du pointeur sur une struct était choisi pour éviter d'éventuelle ralentissement par un trop grand appel de la struct.

    Comment, s'en, passer par le typedef struct _nom *nom peut on obtenir le même resultat éviter des ralentissement du programme par une trop grand appel à la struct.

    Merci par avance.

  7. #7
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 214
    Points : 10 140
    Points
    10 140
    Par défaut
    Comment, s'en, passer par le typedef struct _nom *nom peut on obtenir le même resultat éviter des ralentissement du programme par une trop grand appel à la struct.
    Des ralentissements...
    La déclaration d'une structure ou de plusieurs variables ou même faire 'struct mastructure var' a chaque fois ne ralenti on rien le programme.


    Si on ne doit pas faire comme ça et donc éviter de passer par un pointeur comment fait-on alors quand on à une struct dont on doit se servir de très nombreuse fois le but du pointeur sur une struct était choisi pour éviter d'éventuelle ralentissement par un trop grand appel de la struct.
    Tu sais on sait coder depuis des années en C et on a fait quelque jeux avec , donc on sait de quoi on parle merci.
    Je doute qu'il a dit de cacher un pointeur , surtout que on plus il traîne sur ce forum

    On de te demande juste de ne pas faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef struct _sprite *sprite;
    mais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef struct _sprite sprite;
    Et donc dans ton code tu fera :
    Et donc tu ne cache pas ton pointeur , compris ?


    Pour l'indentation qu'est-ce que je devrais amélioré dans le codes.
    Il devrait faire une vidéo sur l'indentation alors
    Plus sérieusement la présentation du code et pour ma part aussi importante que le résultat , si le code est moche , j'en vois pas l’intérêt (surtout quand on doit le montrer pour avoir de l'aide).

    Sinon un autre conseil que tu dois suivre , évite les variables a une lettre... , surtout les majuscules (les majuscules sont plus pour les defines et structure).
    Donc le I Majuscule tu le vire , int a,int b, int c c'est vraiment n'importe quoi comme nom , si tu manipuler un triangle j’aurais pas dit mais la ... , ça serait a la limite plus r,g,b.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void My_SDL_FreeSurface(SDL_Surface *I)
    {
      SDL_FreeSurface(I);
    }
    Cette fonction ne sert vraiment a rien

    Et de changer :
    par Sinon je confirme ce qu'a dit précédemment LittleWhite.

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut
    Merci pour ton aide et ta réponse.
    En aucune façon je ne cherche à contesté ni a remettre en question votre savoir faire, je cherche juste a comprendre ; ce que j'essaye juste, c'est de comprendre la différence de point de vu entre différents programmeurs sur ce problème de pointeur de struct car ce que dit Jacque Olivier Lapeyre dans sa vidéo sur les pointeurs de struct et ce que vous dite vous et différent et donc j'ai 2 point de vu différent et donc il est très difficile de savoir qui on doit écouter.

    L'explication donner par Jacque Olivier Lapeyre est : (voir l'explication à partir de la 5eme minutes)


    que quand on passe une struct à une fonction on envoie en faite toute la struct donc si notre stuct à par exemple 20 variables et bien la fonction va dupliquer les 20 variables dans la mémoire.

    C'est pour ça qu'il dit quand passant un pointeur de struct à une fonction on envoi qu'une variable donc le pointeur sera le seul dupliquer ; ce qui évite si on a besoin d'utiliser de nombreuses fois la fonction qui appel la struct que la fonction a chaque fois recopie les variable de la struct ce qui aura pour effet d'alourdir de ralentir le programme.

    Voilà c'était pour ça je voulais simplement savoir qui a raison en faite. En aucun cas je ne remet en question votre savoir faire ni vos connaissance car je suis tout a fait conscients que je suis un noob en informatique.

  9. #9
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 214
    Points : 10 140
    Points
    10 140
    Par défaut
    quand on passe une struct à une fonction on envoie en faite toute la struct donc si notre stuct à par exemple 20 variables et bien la fonction va dupliquer les 20 variables dans la mémoire.
    ça on le sais , mais ça n'a rien a voir avec cacher son pointeur dans une struct , il y a le signe & pour mettre l'adresse.
    par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Sprite sprite;
    mafonction(&sprite);
    et ça ralenti nullement le programme.

  10. #10
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut
    Ok merci pour la réponse

    Mais lui (Lapeyre) ne fait pas comme vous c'est un informaticien expérimenter pourtant ?

  11. #11
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 214
    Points : 10 140
    Points
    10 140
    Par défaut
    Mais lui (Lapeyre) ne fait pas comme vous c'est un informaticien expérimenter pourtant ?
    Et ?
    Probablement que c'est pour l'usage de son cours pour expliquer les structures et les pointeurs, je crois pas qu'il le met comme obligation si tu devait faire un malloc sur chaqu'une de tes structures alors la oui ça serait très long niveau programme (dans le sens dans un jeux vidéo oui il risque d'y avoir pas mal de structure).
    Surtout que dans son exemple ça semble bête de faire un pointeur+malloc pour une structure point
    Donc a part pour un but pédagogique non cet exemple est pas vraiment à reproduire.

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut
    OK merci pour les précisions
    Pourtant dans tous ses programmes il fait comme ça en tout cas tous ceux que j'ai vu.

  13. #13
    Membre confirmé Avatar de smartties
    Homme Profil pro
    Dev
    Inscrit en
    Février 2010
    Messages
    222
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Dev

    Informations forums :
    Inscription : Février 2010
    Messages : 222
    Points : 496
    Points
    496
    Par défaut
    Citation Envoyé par hbx360 Voir le message
    Ok merci pour la réponse

    Mais lui (Lapeyre) ne fait pas comme vous c'est un informaticien expérimenter pourtant ?
    Salut,

    Je ne sais pas qui est ce [COLOR=#3e3e3e]Jacque Olivier Lapeyre, mais en parcourant sa chaîne, on peux trouver un de ses jeux qui nous ramène dans les années 90, ne me donnent pas l'impression d'avoir à faire à un "Informaticien expérimenté". Mais plutôt à un développeur du dimanche.

    Suis le conseil de Kannagi et LittleWhite, c'est juste une question de visibilité.

  14. #14
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut
    Merci pour ton commentaire il explique lui même qu'il a un BAC +5 en informatique et à fait une thèse je crois dans l'imagerie.

  15. #15
    En attente de confirmation mail

    Profil pro
    Inscrit en
    Septembre 2013
    Messages
    639
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 639
    Points : 2 347
    Points
    2 347
    Par défaut
    Bonjour,

    le "développeur du dimanche" vous répond. Le but c'est de mettre tout le monde d'accord, mais si ce but n'est pas atteint, je m'en moque, hein, j'ai d'autres choses à faire, notamment parce que je travaille le jour comme la nuit. En revanche il est rare que je programme le dimanche.


    (...) il explique lui même qu'il a un BAC +5 en informatique et à fait une thèse je crois dans l'imagerie.
    Oui. Dans la "restauration de vieux livres" plus précisément. Ce qui exigeait des connaissances assez poussées dans l'analyse d'image et la capacité à écrire des applications puissantes et robustes.

    (...) en parcourant sa chaîne, on peux trouver un de ses jeux, et son site qui nous ramène dans les années 90, ne me donnent pas l'impression d'avoir à faire à un "Informaticien expérimenté". Mais plutôt à un développeur du dimanche.
    Je suis peut-être un développeur du dimanche, mais j'ai formé un bon millier d'étudiants en informatique entre 2001 et aujourd'hui, parfois sur des technologies dernier cri, parfois selon de vieilles méthodes... cela dépend des écoles dans lesquelles je suis intervenu et / ou interviens.

    Maintenant venons-en à la discussion sur les typedefs.

    Regardons d'abord ce code-ci :

    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
     
    typedef struct _lapin lapin;
     
    struct _lapin {
        /* plein de champs bien lourds */
    };
     
    void fonction_quelconque (lapin l) /* oui une variable dont le nom n'à qu'une lettre, que cela plaise ou non */
    {
        /* gnagnagna */
    }
     
    void autre_fonction (void)
    {
       lapin lap = /* initialisation avec ce que vous voulez */;
     
       fonction_quelconque (lap);
    }
    Dans ce code la variable lap est copiée avant l'exécution de fonction_quelconque... et cette copie est lourde parce que la struct est copiée.

    (Oui, vous savez tous cela, et normalement vous savez tous également ce que je vais écrire après, c'est même dingue qu'il me faille le justifier, mais cette nuit je peux me permettre de perdre une heure, ça tombe bien).

    Maintenant on regarde le deuxième code :

    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
     
    typedef struct _lapin lapin;
     
    struct _lapin {
        /* plein de champs bien lourds */
    };
     
    void fonction_quelconque (lapin* l) /* oui une variable dont le nom n'à qu'une lettre, que cela plaise ou non */
    {
        /* gnagnagna */
    }
     
    void autre_fonction (void)
    {
       lapin lap = /* initialisation avec ce que vous voulez */;
     
       fonction_quelconque (&lap);
    }
    Dans cette version-là, seul un pointeur (dont la valeur est l'adresse de lap) est copié. On évite donc de perdre en performance.
    Le fait que le paramètre de fonction_quelconque soit de type lapin*ne cache pas le fait que c'est un pointeur.
    C'est très bien : selon qu'une variable est déclarée de type lapin ou de type lapin*, on sait si c'est un pointeur ou non.

    Beaucoup de programmeurs C écriront donc cela ainsi. Tout commence par un typedef struct _lapin lapin;

    Examinons une troisième version (purée j'ai vraiment du temps à perdre) :

    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
    19
     
    typedef struct _lapin* lapin_ptr;
    typedef struct _lapin   lapin_s;
     
    struct _lapin {
        /* plein de champs bien lourds */
    };
     
    void fonction_quelconque (lapin_ptr l) /* oui une variable dont le nom n'à qu'une lettre, que cela plaise ou non */
    {
        /* gnagnagna */
    }
     
    void autre_fonction (void)
    {
       lapin_s lap = /* initialisation avec ce que vous voulez */;
     
       fonction_quelconque (&lap);
    }
    Cette version-là a à peu près les mêmes avantages que la précédente.
    Je dis "à peu près" car l'idée derrière cette version, c'est que les programmeurs qui travaillent ensemble sur le même projet doivent s'être d'abord mis d'accord entre eux sur les conventions de nommage à respecter strictement. On peut encore savoir si une variable est un pointeur ou non, mais à condition de connaître cette convention et à condition que tout le monde la respecte effectivement.

    Est-ce que la version 2 est meilleure que la version 3 ? Ou le contraire ? Les gens qui codent en C pour le côté "bas niveau" préfèrent généralement la version 2, question de culture sans doute. Ceux qui se servent de C pour écrire des applications pourront préférer la version 3, question de culture là-aussi.

    Cette version 3 peut exister en d'autres variantes.

    Première variante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    typedef struct _lapin* lapin_ptr;
    typedef struct _lapin lapin;
    /* etc */
    Tout va bien. Pas d'ambiguïté. Il y a des programmeurs C qui feront ainsi.

    Maintenant considérons une deuxième variante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    typedef struct _lapin* lapin;
    typedef struct _lapin lapin_s; /* ou S_lapin comme j'ai pris l'habitude de faire */
    /* etc */
    C'est cela que je fais dans mes vidéos et dans le code que j'écris la nuit. Quand je travaille avec d'autres programmeurs, je me range à leur choix, et c'est vrai qu'en général leur choix est typedef struct _lapin lapin; parce que, historiquement, c'est comme ça que "tout le monde" fait.

    Voici les raisons pour lesquelles je procède ainsi. Je ne les précise pas pour vous convaincre d'en faire autant, mais juste pour ne pas passer pour le neuneu qui n'a rien compris à la programmation.

    Dans mes vidéos pédagogiques, j'ai utilisé le C comme langage pour écrire des (petites) applications, et non comme langage pour faire de la programmation système ou autre domaine "bas niveau" dans lequel il excelle. Dans ce contexte, j'ai pendant longtemps écrit des programmes dans lesquels on travaille toujours avec des pointeurs de structs et non des structs. En gros tout ce qui n'est pas type de base (int, char, etc) est un pointeur de struct. Cela nous rapproche des langages pour écrire des applications (Java par exemple : il y a les types de bases, et tous les autres qui sont des pointeurs cachés). Donc je n'avais que ce type-là de typedef :

    typedef struct _lapin* lapin;

    La justification de ce choix (que je viens de donner) est expliquée plusieurs fois dans mes vidéos.
    Il y a une vidéo (mais je ne sais plus laquelle) dans laquelle je reviens sur ce point en précisant que ce n'est pas une habitude de programmeur C, et en expliquant pourquoi.

    Un jour j'ai eu besoin, pour faire de petites optimisations, de pouvoir choisir entre travailler avec des structs directement ou bien des pointeurs de structs. C'est là que la question de laisser tomber la "sémantique par référence uniforme" (le typedef struct _lapin* lapin) s'est posée.
    J'ai pensé "compatibilité ascendante" avec mon ancien code (la compatibilité ascendante étant selon moi un principe qui prévaut largement, en cas de conflit, sur la prétendue lisibilité du code) et j'ai donc ajouté à ce moment-là :

    typedef struct _lapin S_lapin;

    Mais j'ignore si hbx360 est déjà arrivé, dans mes vidéos, au stade où j'ajoute cela.


    Jacques-Olivier Lapeyre
    (avec un s et un trait d'union)

  16. #16
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 431
    Points : 172
    Points
    172
    Par défaut
    Merci beaucoup pour cette réponse et d'avoir pris le temps de répondre Jacques-Olivier Lapeyre cela m'a permit d'avoir des éclaircissements et donc au final on code en fonction du contexte si je comprends biens dans lequel on se trouve.

    Mais j'ignore si hbx360 est déjà arrivé, dans mes vidéos, au stade où j'ajoute cela.
    Je ne saurai dire ; je me suis arrêté au cours 122 pour l'instant.
    Et si j'ai vu ce cours désolé j'ai dû oublié cette mention.

    Merci à tous encore pour toutes vos réponses et l'aide que vous m'avez apporter.

Discussions similaires

  1. Rebond de la balle sur les bords d'un terrain
    Par sperca dans le forum SDL
    Réponses: 8
    Dernier message: 19/08/2009, 13h49
  2. Probleme d'afficage fenetre SDL
    Par fab101 dans le forum SDL
    Réponses: 3
    Dernier message: 19/03/2006, 18h31
  3. Rebond d'une balle sur un sol incliné
    Par franco01 dans le forum Algorithmes et structures de données
    Réponses: 18
    Dernier message: 05/02/2006, 01h20
  4. [SDL] Integration fenetre SDL dans fenetre C# ?
    Par salammbo dans le forum OpenGL
    Réponses: 3
    Dernier message: 07/02/2005, 09h47
  5. signal carré sur port //
    Par MLOLO dans le forum C++
    Réponses: 2
    Dernier message: 14/01/2005, 02h02

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