开发者

arrays of not yet defined types (incomplete element type)

Is it possible to make an array of declared but not defined types? This is what I would like to do:

typedef struct _indiv indiv;
typedef indiv pop[];

and let somebody else decide what an individual's members actually are by defining the struct _indiv in another .c or 开发者_Python百科.h file (and then linking everything together).

(For the semantics, indiv is an individual and pop is a population of individuals.)

But the compiler complains:

error: array type has incomplete element type

I could replace the second typedef by

typedef indiv * pop;

And use pop like an array by accessing the elements like p[i] (with p of type pop), but if I do that the compiler will complain that

error: invalid use of undefined type ‘struct _indiv’
error: dereferencing pointer to incomplete type

I suppose since typedef struct _indiv indiv is only a declaration, the compiler does not know at compile time (before the linkage) how much space the struct requires and that it doesn't like it, thus forbiding to do what I'm trying. But I would like to know why and if there is a possible way to acheive what I want.

Thanks


If you want this source file to manipulate items of type indiv, then you have 2 choices.

1) Declare the structure, but don't define it. Use only pointers to the structure. Never dereference them:

 struct _indiv;
 typedef struct _indiv indiv; 
 typedef indiv * pop;
 //sizeof(_indiv) is not known, how many bytes should we allocate?
 pop p = malloc(N*unknownSize); 
 //this line will fail because it does not know how many bits to copy.
 p[0] = getIndiv();

2) define the complete structure:

 struct _indiv
 {
    int id;
    char* name; 
    /*...*/
 };
 typedef struct _indiv indiv; 
 typedef indiv * pop;
 pop p = malloc(N*sizeof(indiv));
 //Now this line can work.
 p[0] = getIndiv();

The suggestion to define a dummy 'indiv' is a bad one:

 --- file1.c

 struct _indiv
 {
    char dummy;
 };
 typedef struct _indiv indiv; 
 typedef indiv * pop;
 pop p = malloc(N*sizeof(indiv));  //this will allocate N bytes.
 //This will generate code that copies one byte of data.
 p[0] = getIndiv();

 ---realIndiv.c

 typedef struct _indiv
 {
    int id;
    char* name; 
    /*...*/
 } indiv;
 indiv getIndiv();
 {
    indiv i = /* whatever */;
    return i;    //this will return 8+ bytes.
 }   

When you do this, the first file will be manipulating a differently sized item than the "real" indiv struct, and you are sure to get unexpected behaviour.


You are right that the compiler doesn't know the size of incomplete types (in your example, struct _indiv is an incomplete type), which is why you cannot declare a variable of such a type. This includes creating an array of such types.

However, this doesn't really matter, because if you don't have the complete definition of the type, then you can't sensibly access its members anyway: if you write p[i].foo, how do you know if the type actually has a member called foo, and if it does, what type it is?

If you want the struct type's members to be defined in another .c file (this is known as an "opaque type"), then you must only ever create and handle pointers to the struct. Your other .c should contain all the code that actually accesses the struct itself. The file that has only the incomplete type would contain code like:

indiv *i1, *i2;

i1 = new_individual("foo"); /* Create an individual */
i2 = new_individual("bar");

print_individual(i1);

...and the source file with the complete definition of the struct would contain the implementation of new_individual(), print_individual() and so on.

Under this scheme, the easiest way to deal with a population is to make it an array of pointers to indiv structs.


You can only define array of pointers to an undefined type, because you don't know size of that type.

Note that in C language you can define the same struct differently in many places. You can use this technique: Simply define your struct anyhow, then you can freely define and use pointers to that type. And then define the real struct with the same name somewhere else. Also you get the same effect when you simply use arrays of void*.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜