CASSE BRIQUE [C] [SDL]

Messages postés
1466
Date d'inscription
mardi 20 février 2007
Statut
Membre
Dernière intervention
7 février 2011
- - Dernière réponse : smartties
Messages postés
23
Date d'inscription
jeudi 11 mars 2010
Statut
Membre
Dernière intervention
1 septembre 2014
- 9 mars 2014 à 13:35
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/51791-casse-brique-c-sdl

uaip
Messages postés
1466
Date d'inscription
mardi 20 février 2007
Statut
Membre
Dernière intervention
7 février 2011
-
Salut,
C'est rigolo, je procède de la même façon (main() dans .c et autre code dans .h).
Mais si tu veux gagner en rigueur, rien de mieux que de passer au C++, justement (selon moi).
Parce-qu'en C++, tu es "obligé" de structurer ton code en .h/.c.
En C, la structuration modulaire est plus abstraite. Dis toi que tu sectionnes ton projet en modules. Si par exemple, tu fais un client de tchat, tu peux imaginer un module "connexion" (gestion des sockets), un module "GUI" (gestion de l'interface), et un module "données" (gestion des buffers de flux entrant/sortant).
Là, tu fais pour chacun de ces 3 modules un .h et un .c. Dans le .c, tu définies toutes tes fonctions utiles (par exemple pour le module "connexion" : connexion, déconnexion, écriture, lecture, etc) et dans le .h tu écris le prototype de ces fonctions. Ainsi, si tu as besoin des fonctions de "connexion" dans le module "GUI", tu ajoutes un petit "#include "connexion.h"" et le tour est joué.
Tu verras qu'en C++, cette procédure est automatique : tu déclares tes classes dans des .h, tu définies le code des méthodes dans les .c, et lorsqu'une classe a besoin d'une autre, #include est là pour ça.

je lirai ton code plus tard :)

Bonne continuation.
ctx_man
Messages postés
285
Date d'inscription
mardi 28 décembre 2004
Statut
Membre
Dernière intervention
20 janvier 2013
-
Personnellement je trouve le C plus rigoureux dans la séparation des fichiers...
Petit rappel, le .h est un fichier d'entête, il est fait pour contenir les définitions et uniquement les définitions, pas le code.
Le code va toujours dans des fichier .C, .CPP, CXX, ... mais pas dans les fichiers .H (a quelques rares exceptions comme les templates en C++ où la on a guerre le choix, sauf qu'on nomme généralement ces fichiers .HPP).
Le compilateur dira rien si vous ne suivez pas cette règle, lui il s'en tamponne. Cependant, ne pas suivre ces règles ca signifie une maintenance bien galère et la quasi impossibilité de réutiliser le code.
Si tu met ton code dans un .h, à chaque fois que tu inclut le .h, tu inclus le code avec, ca devient donc une seconde instance du même code. Ca implique plein de limitations avec des choses vraiment pas simples a débugger.
Donc définitivement non, le code ne vas pas dans les fichiers .h mais dans les fichiers .c.
C'est pas dur du tout en plus.
Par exemple, ton fichier barre.h, fais-en une copie nommée barre.c, tu vires les gardiens (#ifndef BARRE_H_INCLUDED ...#endif), t fais un include de barre.h dedans. Maintenant tu vas dans ton barre.h, tu supprimes tout le code de la fonction (c'est a dire tout ce qu'il y a entre accolade, accolades incluse) et tu met un ';' à la place : SDL_Rect barre(SDL_Surface *ecran, int* boucle);
Tu ajoutes un include de SDL.h car sinon le fichier n'est pas viable seul (ca compilera peut être si SDL.h est inclut ailleurs, mais la compilation seule de barre.c ne peut fonctionner) et vola, le tour est joué, tu as maintenant un fichier .c contenant le code, compilable et linkable, accompagné d'un fichier .h contenant toutes les infos pour permettre d'utiliser ce code depuis n'importe où.
La séparation en .c/.h n'est pas faite pour séparer la GUI du reste ou je ne sais quoi, mais pour séparer le code des définitions afin de permettre la réutilisation du code.
Le C++ n'automatise absolument pas cette procédure, rien n'empêche de faire de même, c'est juste que les IDE proposent l'ajout de class plutôt que l'ajout de code, ce qui se traduit par l'ajout d'une class modèle pré-décomposée. Ça n'est pas fait en C pour la simple et bonne raison qu'il n'y a pas de classes et donc rien que l'on puisse pré-décomposer.
uaip
Messages postés
1466
Date d'inscription
mardi 20 février 2007
Statut
Membre
Dernière intervention
7 février 2011
-
Salut,
Quelques petites remarques...
"Petit rappel, le .h est un fichier d'entête, il est fait pour contenir les définitions et uniquement les définitions, pas le code."
> Justement, la définition d'une fonction est son code :) tu voulais dire "déclaration", sans doute (le prototype, quoi).

Pour ce qui est de la simplicité, je pense que c'est quand même plus simple d'avoir un .c et plusieurs .h. je dis pas que c'est mieux, au contraire, mais ça permet d'avoir un code linéaire vertical, et non pas un ensemble de fichiers qui contiennent tel ou tel .h, etc. C'est pour cette raison que la plupart du temps, les "débutants" procèdent comme cela ("débutant" n'est pas péjoratif, ici). Découper en plusieurs .c prend généralement un peu plus la tête, au départ (erreurs d'inclusion, etc).

Enfin, mais là c'est pour taquiner, on peut faire de la pseudo-POO en C.

Sinon, je suis d'accord avec toi sur le reste :)
ctx_man
Messages postés
285
Date d'inscription
mardi 28 décembre 2004
Statut
Membre
Dernière intervention
20 janvier 2013
-
Le prototype d'une fonction est un des types de définition/déclaration qu'on met dans un fichier .h.
Mais on met également les structures, les enums, les #define, les #typedef, ....
C'est pour ca que j'ai parlé de définitions et non pas de prototype.
Ce découpage n'est pas vraiment pour faire de la pseudo POO bien que faire de la pseudo POO passe par ce découpage.
Il s'applique toujours pour plusieurs raisons :

- beaucoup plus lisible. Puisque qu'un fichier C ne contient que le code d'une partie précise, il n'est pas pollué par le reste. C'est très proche de la notion d'objet, mais c'est pas pour autant que c'est de la POO.

- beaucoup plus facile a maintenir. Le code étant découpé il est plus facile d'opérer des mises à jour sur une portion sans attaquer le reste. Ça évite aussi les fichier .C qui font 250 000 lignes. Ce qui évite d'alourdir inutilement les IDE, les compilos et le cerveau qui doit s'y retrouver dans tout ce foutoir. 250 000 lignes peut paraître un chiffre énorme pour un débutant, mais non, ca vient très très vite. Par exemple, en ce moment au boulot je travail sur un petit utilitaire en C# (langage qui nécessite moins de code que le C ou C++ pour obtenir le même résultat). Ça fait 1 semaine que je bosse dessus, le truc fait déjà 6000 lignes de code. Je pense qu'une fois fini il devrait être dans les 10 000. Tout ca pour un tout petit utilitaire qui prend des données d'une base pour les injecter dans une autre (bon il fait un tout petit peu plus que ca, mais vraiment pas grand chose). Alors imagine un vrai gros projet sur lequel bossent une dizaine de personne.

- réutilisation. Si demain tu décides de séparer ton programme en un .exe et une .dll laquelle contient, par exemple, toute la gestion de l'affichage, ton code restera quasiment inchangé. De même, si tu décide de créer un nouveau programme qui utilise en grande partie ce que tu as déjà fait dans celui-la, tu pourra te contenter d'inclure les fichiers plutôt que de partir dans un copier/coller qui risque plus de tout casser qu'autre chose.

- Moins de problèmes "étranges". En mettant le code dans le .h tu dupliques le code à chaque fois qu'il est inclut, plutôt que de réutiliser le code en question. Dans la DLL tu met un code de gestion de l'affichage (dessins des barres/briques/...) et dans l'exe tu fais des appels à ces fonctions. Donc tu as inclut le fichier H dans les deux, or, le fichier H contient le code, donc ton exe ne fera pas appel à la DLL contrairement à ce que tu pouvais penser, puisqu'il dispose du code 'en local'. Résultat, non seulement tu as une DLL qui sert à rien, mais en plus tu peux être amené a te dire que tu peux mettre à jour le code d'affichage et redistribuer juste la DLL, ce qui aurait été vrai, mais vu que ton exe n'utilise pas la DLL, bah ca marchera pas. Et ce genre de truc, crois moi, tu va galérer comme pas permis pour comprendre d'où vient le problème, parce que le compilo te laissera faire, le debugger ne verra pas le problème et l'exe fonctionnera parfaitement.

- respect des standard. C'est comme ca qu'on doit faire (ca fait parti de la norme du C et du C++), ce n'est pas parce que le compilateur te permet de faire autrement qu'il faut en profiter. A moins de pas avoir le choix, mais vu l'age de la norme, le nombre de cas où on a pas le choix est proche de 0. A la limite, quand tu sais très bien ce que tu fais et que tu maitrise bien les impactes, tu peux te permettre de prendre des libertés sur la norme. Mais quand ca n'a aucun intérêt, je vois pas pourquoi le faire. La norme est la pour faire abstraction d'un paquet de problèmes potentiels.

Je ne suis absolument pas d'accord avec les mauvaises pratiques qui "sont plus simple pour un débutant". Une mauvaise pratique reste une mauvaise pratique, quand on s'y habitue ca devient très dur de s'en défaire. De plus, il a beau être débutant il dit aussi vouloir faire un bilan avant de se mettre au C++. Bah voilà, c'est un bilan, y'a du bon et du mauvais, lui montrer les mauvais points pour qu'il progresses est à mon sens plus utile que de les occulter. Et s'il conserve cette pratique pour se lancer dans le C++ il va droit dans le mur. Enfin ce n'est que mon avis.
uaip
Messages postés
1466
Date d'inscription
mardi 20 février 2007
Statut
Membre
Dernière intervention
7 février 2011
-
Tu es décidément têtu :)
Tu cherches à me convaincre de quelque chose dont je suis déjà d'accord avec toi.
Ton dernier paragraphe est complètement faux. Je l'ai dit et répété, tout mettre dans un .h et inclure dans un .c n'est pas du tout la bonne méthode. On est d'accord là dessus. Mais c'est compréhensible qu'un débutant fasse ça, parce-que c'est plus simple que de créer divers .c. Je n'ai dit que ça, rien de plus.

Concernant le mot "définition", je n'ai jamais entendu de "définition de structure" ou autre, mais seulement des déclarations.
Pour moi, on ne peut définir que 2 entités : fonctions et variables. Les enumérés et les structures étant des équivalents des types, on ne peut que les déclarer.Donc, .h déclarations, et .c définitions.
ctx_man
Messages postés
285
Date d'inscription
mardi 28 décembre 2004
Statut
Membre
Dernière intervention
20 janvier 2013
-
Oui je suis têtu, mais non je ne cherche pas a te convaincre.
D'autant que j'avais bien compris que tu étais en parti d'accord avec moi. Cependant j'ai préféré complété mon premier poste compte tenu de ta réponse, afin d'être plus clair au vu de tes remarques, sans compter que tu n'es pas le seul lecteur.
Moi je dis définition, déclaration ca me va aussi. Il n'y a pas grandes différences.
Enfin, je vois pas en quoi mon dernier paragraphe est complètement faux. Tu dis que tout mettre dans un .h n'est pas la bonne méthode, tu dis donc la même chose que moi. J'en conclut donc que tu n'es pas d'accord sur le fait que je dise qu'une mauvaise pratique ne se perd pas facilement. Mon expérience m'a toujours montré a quel point les habitudes, bonne ou mauvaise, sont dures à perdre, tu as tout à fait le droit de ne pas être d'accord, comme je l'ai dis, ce n'est que mon avis. Mais ca ne le rend pas faux pour autant. Bref, je vois vraiment pas en quoi c'est "complètement faux". Et puis je n'ai jamais dit que ce n'était pas compréhensible pour un débutant de faire ainsi, je dis juste qu'il ne faut pas faire comme ca et j'explique comment faire selon moi, j'oblige personne à adhérer, approuver ou je ne sais quoi d'autre.
uaip
Messages postés
1466
Date d'inscription
mardi 20 février 2007
Statut
Membre
Dernière intervention
7 février 2011
-
Ben, ce n'est pas pareil, non.

int a; //Déclaration de variable
a = 10; //Définition de variable
int b = 5; //Déclaration + définition de variable

int max(int a,int b); //Déclaration de fonction (prototype)
int max(int a,int b) { return (a > b)?a:b; } //Définition de fonction

struct c {
int a;
int b;
}; //Déclaration de structure

typedef struct {
int a;
int b;
} c; //Déclaration de structure en nouveau type

c var={10,5}; //Déclaration + définition de variable

Enfin, c'est comme ça que le vois.
ctx_man
Messages postés
285
Date d'inscription
mardi 28 décembre 2004
Statut
Membre
Dernière intervention
20 janvier 2013
-
Hum, ouais, pourquoi pas.
Personnellement je n'ai pas le même vocabulaire.

a = 10; //Définition de variable, moi je dis valorisation
int max(int a,int b) { return (a > b)?a:b; } //Définition de fonction, moi j'appel ca "le code" ou "le corps" d'une fonction.

Et, toujours pour moi, une valorisation ca reste du code, ca n'a donc rien a faire dans un .h (encore une fois, y'a des cas où on y peut rien).

Mais bon voila, cette petite différence de vocabulaire n'est pas bien importante.
smartties
Messages postés
23
Date d'inscription
jeudi 11 mars 2010
Statut
Membre
Dernière intervention
1 septembre 2014
-
Ca fait bizarre de revoir son code source, après 2ans.
smartties
Messages postés
23
Date d'inscription
jeudi 11 mars 2010
Statut
Membre
Dernière intervention
1 septembre 2014
-
et encore plus après 4...