[gull] Subtilité de C n° 4 : déclaration de struct
Leopoldo Ghielmetti
leopoldo.ghielmetti at a3.epfl.ch
Sat Apr 19 14:21:33 CEST 2008
On Fri, 2008-04-18 at 19:02 +0200, Marc Mongenet wrote:
...
> > 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. ;-)
Je me suis mal exprimé.
> >
> > 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
Et aussi en Modula2. Je me rappelle que je l'utilisais souvent (et je
l'utilise souvent en C aussi).
> 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` ?
ex3.c: In function ‘f’:
ex3.c:8: error: dereferencing pointer to incomplete type
Ce qui me parait évident car au moment du return la structure s n'est
pas encore entièrement déclarée.
> Que retourne f() ?
Quand ça compilera je vais te répondre. :-)
En tout cas je m'attends à ce que ps.p pointe sur la structure s
déclarée à l'intérieur de la fonction f, c'est à dire celle qui contient
ps. Donc il s'agit la d'une structure qui pointe sur une structure
identique.
> Marc Mongenet
>
> PS : Tout ces subtilités sont également valables pour les unions.
Une union n'est rien d'autre qu'une structure ou tous ses membres ont un
offset 0. Donc je m'attends à un comportement identique.
ciao, Leo
More information about the gull
mailing list