Re: [gull] Subtilité de C n° 4 : déclaration de struct
Marc Mongenet
marc at mongenet.ch
Fri Apr 18 19:02:24 CEST 2008
Le 17/04/08, Leopoldo Ghielmetti<leopoldo.ghielmetti at a3.epfl.ch> a écrit :
>
> Il giorno mer, 16/04/2008 alle 21.31 +0200, Marc Mongenet ha scritto:
>
> > Le 15/04/08, Leopoldo Ghielmetti<leopoldo.ghielmetti at a3.epfl.ch> a écrit :
> >
> > > On Tue, 2008-04-15 at 02:37 +0200, Marc Mongenet wrote:
> > > >
> > > >
> > > > ----------------------- ex2.c
> > > > struct s { int i; } v;
> > > >
> > > > void f(void) {
> > > > struct s;
> > > > struct ps { struct s *p; } ps;
> > > > struct s { int j; } v;
> > > > ps.p = &v;
> > > > ps.p->j = 0;
> > > > }
> > > > -----------------------
> > >
> Oui, en effet, je me suis mal expliqué. La structure s est de toute
> façon redéclarée.
> Les deux codes seraient par contre identiques si la structure ps était
> déclarée juste après la structure s
Tout à fait.
>
> Tu aurais aussi un joli effet si tu ajoutais la déclaration suivante
> juste après la déclaration de ps et avant la declaration de la structure
> s:
> int ssize = sizeof(struct s);
>
> Je n'ai pas vérifié en compilant la chose mais j'imagine que dans le
> premier cas ça marche et ssize prend la valeur correspondante à la
> taille de la structure s, dans le deuxième cas ça plante à la
> compilation car la structure s n'a pas encore été déclarée.
>
Il y a une erreur de compilation car la structure s est incomplètement
déclarée, et qu'on n'a pas le droit d'utiliser sizeof sur un type
incomplètement déclaré, nuance. ;-)
>
> Dans le premier cas rien (car il confirme que la struct s existe bel et
> bien), dans le deuxième il annonce la future déclaration de la structure
> s. Ça ne me parait pas si tordu que ça.
Dans le 2e cas, le « struct s; » déclare un type incomplet.
C'est un concept un peu différent d'une déclaration avancée
à la Pascal, car on n'est pas obligé de compléter plus bas un
type incomplet, et on peut l'utiliser pour toute opération qui
n'a pas besoin de savoir ce qu'il y a dans la structure.
L'exemple typique d'usage des types incomplets et celui des
pointeurs opaques. Ça s'utilise en C, c'est un idiome courant
de C++ (sous le nom de Pimpl notamment), et je vois que ça
existe même en Ada : http://en.wikipedia.org/wiki/Opaque_pointer
Exemple en C adapté de l'exemple de Wikipédia :
--------------------------- opaque.h
typedef struct foo *foo_handle;
foo_handle create(int);
void destroy(foo_handle);
int do(foo_handle, int);
---------------------------
Sans savoir ce qui se trouve dans struct foo, on peut
pourtant créer, détruire et manipuler des objets de ce type
par l'intermédiaire de foo_handle.
Une dernière variation du quizz pour conclure :
----------------- ex3.c
struct s { char c; };
unsigned f(void) {
struct s;
{
struct ps { struct s *p; } ps;
struct s { char c1; char c2; };
return sizeof *ps.p;
}
}
-----------------
Que me dit `gcc -c ex3.c` ?
Que retourne f() ?
Marc Mongenet
PS : Tout ces subtilités sont également valables pour les unions.
More information about the gull
mailing list