[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