FlyingBird a écrit :
typedef struct test
{
void *content;
struct test_ *bob;
} test_;
I don't understand why the struct can be written like this. More
specifically, why doesn't the compiler report an error when it sees
struct test_ *bob. test_ is a typedef a struct test. Can we add the
keyword struct before test_? I read FAQ 1.14
http://c-faq.com/decl/selfrefstruct.html but there is no such an
example.
It is perfecty legal to define an incomplete structure name loke this :
struct name
Being incomplete, the compiler don'sn't know what is the size of such a
structure, hence an instanciation of such a type is illegal :
struct name object; /* compile error */
But, and this is the magic of C, it is possible to define a pointer to
such a type.
struct name *p_object;
struct name const *p_object;
This can be used to define :
* a single pointer (not very useful),
* an element of structure (useful for recursive structures like node of
liked lists, trees etc.),
* a function parameter (same behaviour that a void *, but typed, hence
the ability of a type control by the compiler)
This trick is used to implement ADT (Abstract Data Types) that have an
'opaque' type from the outside (interface, user) and a well defined type
in the inside (implementation)
/* xxx.h */
/* add guards... */
/* public incomplete type */
struct xxx;
/* public functions */
struct xxx *xxx_create (void);
void xxx_delete (struct xxx *p_context);
void xxx_function (struct xxx *p_context);
/* xxx.c */
#include "xxx.h"
/* private complete type */
struct xxx
{
int x;
char *y;
};
/* public function */
struct xxx *xxx_create (void)
{
struct xxx *this = malloc(sizeof *this);
if (this != NULL)
{
/* clear */
static const struct xxx z = {0};
*this = z;
}
return this;
}
void xxx_delete (struct xxx *this)
{
free (this);
}
void xxx_function (struct xxx *this)
{
this->x = 123;
}
/* main.c */
#include "xxx.h"
#include <assert.h>
int main (void)
{
struct xxx *p = xxx_create();
if (p != NULL)
{
xxx_function(p);
/* ... */
/* end */
xxx_delete(p), p = NULL;
}
assert (p == NULL);
return 0;
}
--
A+
Emmanuel Delahaye