[gull] Php/MsSQL obsoletes?
Daniel Cordey
dc at mjt.ch
Wed Sep 28 15:18:35 CEST 2005
On Wednesday 28 September 2005 14:47, Leopoldo Ghielmetti wrote:
> Mais tu peut très bien écrire une chose comme celle la (en ANSI C):
>
> module.c:
> void fonction(int a)
> {
> printf("%d\n", a);
> }
>
> module.h:
> void fonction();
>
> main.c:
> include "module.h"
>
> int main()
> {
> float b = 1.0;
> fonction(b);
> return 0;
> }
Exact, c'est la raison pour laquelle j'ai toujours milite pour que la partie
de definition de la signature de la fonction soit UNIQUE et partagee entre la
definition dans la fonction et la declaration en externe. ceci est facile a
realiser avec des #ifdef.
Exemple de ce genre de fichier qui est genere par un GUI :
...
/* Function name */
/* Is it the main program or the function's code ? */
#if defined(_MAIN_SOURCE) && defined(_NPCaseConfirm_SOURCE)
# define NAME_SOURCE main
#else
# define NAME_SOURCE NPCaseConfirm
#endif /* _MAIN_SOURCE && _NPCaseConfirm_SOURCE */
/* Function type */
#define TYPE_SOURCE void
/* Toggle Extern-declaration/definition */
/* is it a declaration of a definition ? */
#ifdef _NPCaseConfirm_SOURCE
# define EXTERN_SOURCE
# define DECLARATION
#else /* _NPCaseConfirm_SOURCE */
# define EXTERN_SOURCE extern
# define DECLARATION ;
#endif /* _NPCaseConfirm_SOURCE */
#if defined(__STDC__) || defined(__cplusplus)
# define ARG_LIST_SOURCE (API *Api, CaseData *casedata)
#else /* __STDC__ || __cplusplus */
# ifdef _NPCaseConfirm_SOURCE
# define ARG_LIST_SOURCE ()
# else /* _NPCaseConfirm_SOURCE */
# define ARG_LIST_SOURCE ()
# endif /* _NPCaseConfirm_SOURCE */
#endif /* __STDC__ || __cplusplus */
/* The real function declaration */
EXTERN_SOURCE TYPE_SOURCE NAME_SOURCE ARG_LIST_SOURCE DECLARATION
/* Undefine all names used */
# undef EXTERN_SOURCE
# undef TYPE_SOURCE
# undef NAME_SOURCE
# undef ARG_LIST_SOURCE
# undef DECLARATION
Le fichier du code de la focntion a :
#define _NPCaseConfirm_SOURCE
Ainsi, seul le fichier de source "recoit" la definition alors que tout autre
appel "recoit" une declaration lors de l'include de ce fichier.
C'est simple et ca permet d'eviter le probleme mentionne. C'est beton et le
compilateur m'a correctement signale les erreurs dans mon code a chaque fois.
C'est le genre de choses qui vous sauve la vie et vous permet de vous passer
des debuggeurs symboliques.
> Et ça passe très bien. Et la plus part des programmes sont encore écrits
> comme ça car c'était une syntaxe courante dans les années 80 et encore
> beaucoup de programmeurs ont ce réflexe.
Je sais... c'est de l'amateurisme !
> Ceci est possible car dans C la vérification des types n'est pas
> obligatoire et on peut s'en passer. Donc on risque d'avoir des problèmes
> de typage.
Oui, mais comme dans tout langage, le profesionnel adopte des disciplines. ca
me parait indispensable, meme si ce n'est pas obligatoire.
> Le fait que je sais qu'on ne perd pas en précision ne m'aide pas
> forcement, il faut toujours avoir bien à l'esprit le type de chaque
> variable pour être sûr de ne pas changer le type sans s'en rendre compte
> (chose qui est bien plus facile de ce qu'on pourrait croire, surtout si
> on utilise des anciennes librairies). Et ceci peut causer pas mal de
> problèmes si on accède au matériel ou si on travaille au niveau du bit.
Oui, le danger reside surtout dans les "masquages" de probleme. Dans le cas
de :
int i;
short x;
int j;
i = 2;
...
x = i;
...
j = x;
Le danger viend du fait que l'on est persuade de manipuler un int avec j,
alors que cette valeurs a ete tronquee plus tout en passant par x = i. On
peut chercher parfois longtemps ce genre de probleme.
> Mais il s'agit quand même d'une conversion qui n'a pas été explicitée
> par le programmeur.
Oui, mais autorissee car sans danger.
>
> > > c = a <--- Erreur, int <> float
> >
> > Non plus... Dans le cas inverse, ca devrait etre flaguer car un float
> > (32 bits IEEE) donne 6.7 chiffres significatifs, alors que int nous
> > donne un peu plus de 9 chiffres significatifs...
> >
> > > Tandis que C laisse passer et considère ça comme:
> > >
> > > b = (long)a
> > >
> > > c = (float)a
> >
> > C'est exactement l'operation qui est effectuee. Et cela ne pose aucun
> > probleme du tout. Par contre, C permet d'ecrire ceci :
>
> Bien sûr qui peut poser des problèmes car la variable à changé de nature
> et le programmeur n'en sait rien.
Non, pas a proprement parle. b est toujours un long, contenant une valeur
long, et c un float contenant un float. Le contenu de a n'a pas change non
plus. Le probleme est beaucoup plus subtile quand on manipule des valeurs
'unsigned'... ca, c'est mesquin :-)
> Pas totalement vrai, p.e. le compilateur cc de Sun c'est une vraie merde
> de ce côté.
Naturellement, tu mentionnes le pire... SUN a toujours privilegie la
performance et leur compilateur est deliberement 'loose' concernant des
points essentiels. Cela a induit de mauvaises pratiques (et comprehension du
langage C) chez de tres nombreux programmeurs :-(
> J'ai vu du code qui donne 1000 Warning sur le gcc et sur le
> cc Alpha de Digital et seulement 100 sur le compilateur cc de Sun. Et
> parfois c'était des vraies merdes.
parfois seulement ?
> S'ils ont utilisé un compilateur
> comme celui la, qui même avec toutes les options de compilation ne donne
> rien, il est normal qu'ils n'ont pas vu certaines fautes. Il est vrai
> qu'ils auraient pu utiliser lint ou tout autre programme similaire. Mais
> je ne dirais pas qu'il s'agit d'une négligence commise sciemment, juste
> d'une négligence qui peur aussi être due simplement à l'ignorance.
Et l'igonrance est coupable quand on choisi de rester ignorant. Le standard
ANSI existe depuis trop longtemps pour qu'on puisse pretendre a l'ignorance.
La lecture du standard eclaire justement un certain nombre de points
dangereux dont tout programmeur C devrait etre averti.
dc
More information about the gull
mailing list