Why is forward declaration of structure not workin

2019-08-12 17:28发布

问题:

Isn't forward declaration, whether for structures or functions, supposed to do what forward declaration is expected to do, ie, to let us use the structure or function before they are defined? Why is the forward declaration of a structure not working in my code? And the main thing that just misses me, is forward declaration of structures of any use in C at all? When is it used? Can you please give me a small C program example to illustrate this?

My program gives the error error: storage size of 'x' isn't known|.

#include<stdio.h>

struct test;

int main(void)
{
struct test x;
printf("%zu",sizeof(x)); //Gives Error
//printf("%zu",sizeof(struct test));//This fails too
}

struct test
{
    int a;
    char b;
};

New Edit I tried to do what Carl Noum said,but even this is not working:

#include<stdio.h>

struct test;
void foo(struct test*);

int main(void)
{
struct test x={53,'x'},*ptr=&x;
foo(ptr);
}

void foo(struct test* p)
{
    printf("%d,%c",p->a,p->b);
}

struct test
{
    int a;
    char b;
};

回答1:

The compiler has to know the struct's layout when it compiles the main function.

A forward declaration is useful if you only have a pointer but not the actual type.

For example if you have a struct that contains a pointer to another struct

struct foo {
  struct bar *b;
  ...
};

It is also essential if the bar also contain foo like

struct bar;

struct foo {
  struct bar *b;
};  

struct bar {
  struct foo f;
};

In this case you have to have bar pre-declared.

A forward declaration usually means that you don't have to include .h file inside other .h file. This can speed up compilation significantly if the .h file is big.



回答2:

Functions yes, structures no. struct test is an incomplete type where you use it.

A common use case for incomplete types is to declare an opaque type. In a header file, you declare:

struct test;

And then some API that uses struct test only via pointers:

int func1(struct test *);
struct test *func2(void);

In the accompanying implementation, you include the full declaration so that your functions know what to do with the structure:

struct test
{
    int a;
    char b;
};

void func1(struct test *t)
{
    return t->a;
}

Edit:

Your new code doesn't do anything differently - you're still trying to operate on an incomplete type, and you still can't do that. In particular, this declaration:

struct test x = {53,'x'};

Can't work if struct test is an incomplete type. You can (generally) only use pointers to an incomplete type. In this case, that might mean creating a function that allocates and returns a pointer to a new structure, rather than trying to declare and initialize one on the stack.



回答3:

Struct type declared by a forward declaration (i.e. an incomplete type) can be used only in a limited number of ways. Applying sizeof to such a truct type is not one of them. On top of that, you can't use incomplete types in object definitions and you cannot access data fields of incomplete struct types.

In other words, sizeof requires a complete type. Your forward-declared struct type is not a complete type. Operator -> also requres a complete type of the left-hand side. Object definition (like struct test x) also requires a complete type.