Ceci est mon dernier message sur le sujet, je me suis déjà étendu longuement à ce propos ailleurs sur ce forum...

Envoyé par
Melem
Dans
cette réponse, j'ai confondu cstdlib (le stdlib.h de C++) avec cstring (le string.h de C++), d'où inclusion d'un fichier d'en-tête inutile et
omission du bon fichier d'en-tête.
Voilà ce que c'est de mélanger C et C++ 
Moi je ne fais que du C, et, je ré-itère, je n'ai jamais eu ce cas, en tous cas pas méchamment : à la première compile, le compilo te jette, et si tu fais gaffe à ce qu'il dit, tu t'en rend compte instantanément..
Ce n'est toujours pas une raison valable pour l'instaurer en Commandement...
Une compile, sur un gros projet, tu en fais (en dev, sur ta cope du code) environ une fois toutes les 5 minutes, au plus 1 fois par heure...
Compiler une fois et te rendre compte et corriger, par rapport à perturber des milliers de lignes, franchement pour moi ya pas photo...

Envoyé par
Melem
Je connais au moins 3 raisons (tous des cas déjà vécus, aussi bien quand je débutais que depuis que je me suis amélioré) qui peuvent causer l'oubli d'un fichier d'en-tête :
- Oubli pur et simple. Les oublis, ça peut arriver à tout le monde.
- Confusion avec un autre fichier d'en-tête. On pense avoir inclus le fichier requis mais en fait on a inclus un autre, probablement un qui a un nom ou un rôle plus ou moins ressemblant ...
Voir plus haut..
Un compilo bien réglé et le fait de faire gaffe à la sortie du compilo t'averti dès le premier passage...

Envoyé par
Melem
- Erreur de jugement. Prends ceci par exemple (exemple vraiment très simple) :
1 2 3 4 5 6
| /* Fichier include1.h */
#if condition
..
#include <stdlib.h>
...
#endif |
1 2
| /* Fichier source1.c */
#include "include1.h" |
Ici aussi, dans source1.c, lorsqu'
on pense que condition vaut VRAI, alors on pense avoir déjà inclus stdlib.h même s'il n'a pas effectivement été inclus. condition peut être une expression simple, complexe ou hypercomplexe. Faire des erreurs sur l'évaluation de sa valeur peut arriver à tout le monde, pas aux débutants uniquement.
Sauf que là c'est une erreur de conception...
si le fichier source1 a besoin de stdlib.h, il faut l'inclure de toutes façons, sans intermédiaires.. Sauf (ce que je mentionnais dans un autre thread) sur les gros projets où on a un "CommonC.h" qui comprendra tous les entêtes généraux (stlib, stdio, time, ctype, string, math par exemple)..
Je ne comprend vraiment pas cette façon de NE PAS vouloir inclure plusieurs fois des fichiers d'entête...
Les #ifdef sont justement là pour vérifier qu'on ne les inclue pas inutilement.. Alors pourquoi se priver de mettre les include là où on a besoin ???
Dans un cas comme le cas cité, si je n'ai pas de "CommonC.h", j'incluerais stdlib ET dans include1.h ET dans include.h ET dans source1.c...

Envoyé par
Melem
On peut tous croire que tu n'as jamais fait d'erreurs de ce genre et que tu n'en feras jamais mais malheureusement, tout le monde n'est pas aussi talentueux que toi. Comme je l'ai dit, toutes ces erreurs me sont déjà arrivées, et j'ai également vu d'autres personnes se faire avoir. C'est un fait, on peut ne pas en discuter.
J'en ai fait, comme tout le monde, mais comme je l'ai dit l'apparition des erreurs étant tellement évidente à la compile, je ne vois pas en quoi établir une règle aussi absurde et sans fondements réels serait une bonne chose : encore une fois, si on doit faire éviter les erreurs de C possibles, autant enlever les notions de pointeurs, de void, etc etc...
Le C est un langage simultanément laxiste et rigoureux, pour des gens qui savent ce qu'ils font..
Comme la langue française peut en même temps être simple et compliquée.. Est-ce pour autant une raison pour écrire en SMS ou ne pas appliquer les règles de grammaire ou d'accord féminin/masculin ???

Envoyé par
Melem
Explique-moi alors pourquoi personne n'écrit :
1 2 3
| long y;
/* 1 kilomètre après */
y = (long)1; |
Pour rappeler que y est un long ?
Parce que là c'est un long, un type élémentaire d'une variable..
Soit tu n'as jamais travaillé sur de très gros projets, ou bien tu ne veux pas voir : la plupart du temps, tu as des dizaines de pointeurs, dans des structures, qui peuvent être des élements de listes, de tableaux, des structures, ce que tu veux, qui sont alloués par exemple à un endroit, puis réalloués à d'autres, éventuellement dans diverses fonctions, et libérés encore ailleurs..
La définition de la structure n'est pas forcément proche : que ce soit la routine d'initialisation, d'allocation, de remplissage, de réallocation, de destruction... D'autre part cette structure peut contenir de nombreux pointeurs, chacun pointant sur de nouvelles structures... etc etc..
Avoir tout sans cast explicite fait que tu te tortures l'esprit en relisant le code, savoir que tel sous-sous-sous pointeur sera (est ??) de tel ou tel type...
ça m'arrive en permanence d'avoir des pointeurs de pointeurs de pointeurs de pointeurs... Chacun étant alloué dynamiquement..
DataSets[k].Source[j].Data[Num].Location[i].Altitude.Value.d
Et encore ce n'est qu'un exemple simple...
Dans les routines d'allocations ou des réallocation, cela sert d'aspect documentaire... Et cmme je le dit plus bas pour "tracker" un changement..

Envoyé par
Melem
Ce n'est pas pour rien que les conversions implicites existent. void * est compatible avec tous les types pointeurs d'objet. Ca ne rime vraiment rien de caster un void *.
Absolument.. Void* existe POUR POUVOIR PASSER UN PARAMETRE QUELCONQUE A UNE FONCTION....
Son utilisation en tant que cast de résultat de fonction est vraiment d'un usage ultra-limité... :
en fait il n'y a que le malloc, et si on veut stocker un pointeur sur quelque chose d'inconnu dans une structure..

Envoyé par
Melem
Si tu modifies un type, tu dois déjà modifier pas mal de choses dans le code source lui-même. Ca se limite rarement à ajouter ou modifier des casts ... (un peu (mais pas vraiment) hors-sujet : cf la signature de Médinoc

).
Sauf que justement, sans cast explicite, tu peux oublier tout un tas de trucs, en particulier dans les allocations ou réallocations..
Un exemple très simple :
devient
Si d'une part tu n'as pas casté, et d'autre part tu as omis sizeof(char), alors tu es dans une grande panade, sur un très gros soft...
C'est tout...

Envoyé par
Melem
Pas tous. Avec gcc par exemple, l'option -W (enable standard compiler warnings), ni même l'option -pedantic (enable warning demanded by strict ISO C (en mode C90)), ne génère pas le message d'avertissement "implicit declaration". Il faut compiler avec les options les plus strictes possibles (-Wall) pour que ce message soit généré. Et déjà ça ce n'est que gcc, mais on ne va pas passer la soirée à étudier cas par cas les quelques milliers de compilateurs C existants.
Comme je n'utlise aucun IDE, que je suis sous Unix/Linux, et que je compile toujours avec gcc en ligne de commande, et j'ai toujours -Wall -strict_prototypes -ansi (-ANSI90)..

Envoyé par
Melem
Je ne connais par contre pas de compilateur qui reste muet devant une conversion implicite d'entier vers pointeur ou de pointeur vers entier même sans options de compilation spéciales, parce que c'est souvent un peu louche.
si tu ne fais pas de conversion EXPLICITE, il suffit d'oublier -Wall et tu ne l'as pas...
Les compilateurs ne restent pas muets, encore faut-il voir sortir les erreurs...

Envoyé par
Melem
J'ai répondu, pour contrer souviron34, que lorsqu'on change un type dans un projet, ce n'est rarement en plantant ou en modifiant des casts qu'on va pouvoir mettre à jour le reste du code. Cela demande beaucoup de changements radicaux. Ceci pour conclure que son argument ne peut pas compter.
C'est tout simplement faux...
Reprend mon exemple plus haut..
Un "gros" changement dans un projet n'est pas vraiment pas rapport au type, mais souvent de transfomer une valeur en un tableau, ou un tableau en une liste (et donc un pointeur) ou un tableau à plus de dimensions.
Si on a casté, avec xemacs par exemple (et je suis sûr que c'est pareil avec les IDE classiques) tu fais "replace / toto = (char *) / toto = (char **) /" et il te positionnera sur toutes les lignes contenant ça et te demandera "remplacer ou non ?".. et tu auras beaucoup moins d'occurences (et donc de possibilités de se tromper) que si tu cherches "toto" ou même "toto ="...
J'ai très rarement vu un changement de vrai type, ou alors c'est que la conception avait mal fait son boulot..
Enfin, je ne m'étendrais plus là-dessus, mais je trouve plus qu'irritant la façon de vouloir inculquer comme le Grand Méchant Diable cette pratique..
Et même de la déconseiller..
Je dirais le mieux serait de dire : les 2 options sont possibles et se défendent..
Mais, d'après tes premières remarques, c'est possible que ce soit parce que vous côtoyez trop C++ que vous pensiez ça.... Ou alors c'est peut-être l'usage des IDE, ou du C côté Windows..
Je n'en ai jamais fait, ni des uns ni des autres, et moi, en C pur, je MAINTIENS QU'IL EST BIEN DE CASTER
Partager