What is 'forward declaration' and the difference between 'typedef struct X' and 'struct X'?

struct forward declarations can be useful when you need to have looping struct declarations. Example:

struct a {
    struct b * b_pointer;
    int c;
};

struct b {
    struct a * a_pointer;
    void * d;
};

When struct a is declared it doesn't know the specs of struct b yet, but you can forward reference it.

When you typedef an anonymous struct then the compiler won't allow you to use it's name before the typedef.

This is illegal:

struct a {
    b * b_pointer;
    int c;
};

typedef struct {
    struct a * a_pointer;
    void * d;
} b;

// struct b was never declared or defined

This though is legal:

struct a {
    struct b * b_pointer;
    int c;
};

typedef struct b {
    struct a * a_pointer;
    void * d;
} b;

// struct b is defined and has an alias type called b

So is this:

typedef struct b b;
// the type b referes to a yet undefined type struct b

struct a {
    b * struct_b_pointer;
    int c;
};

struct b {
    struct a * a_pointer;
    void * d;
};

And this (only in C, illegal in C++):

typedef int b;

struct a {
    struct b * struct_b_pointer;
    b b_integer_type;
    int c;
};

struct b {
    struct a * a_pointer;
    void * d;
};

// struct b and b are two different types all together. Note: this is not allowed in C++

Forward declaration is a promise to define something that you make to a compiler at the point where the definition cannot be made. The compiler can use your word to interpret other declarations that it would not be able to interpret otherwise.

A common example is a struct designed to be a node in a linked list: you need to put a pointer to a node into the struct, but the compiler would not let you do it without either a forward declaration or a tag:

// Forward declaration
struct element;
typedef struct {
    int value;
    // Use of the forward declaration
    struct element *next;
} element; // Complete definition

and so it cant be used for forward declaration

I think that author's point was that giving your struct a tag would be equivalent to a forward declaration:

typedef struct element {
    int value;
    // No need for a forward declaration here
    struct element *next;
} element;

Forward declaration is a declaration preceeding an actual definition, usually for the purpose of being able to reference the declared type when the definition is not available. Of course, not everything may be done with the declared-not-defined structure, but in certain context it is possible to use it. Such type is called incomplete, and there are a number of restrictions on its usage. For example:

struct X; // forward declaration

void f(struct X*) { }  // usage of the declared, undefined structure

// void f(struct X) { }         // ILLEGAL
// struct X x;                  // ILLEGAL
// int n =sizeof(struct X);     // ILLEGAL

// later, or somewhere else altogether
struct X { /* ... */ };

This can be useful e.g. to break circular dependencies, or cut down the compilation time, as the definitions are usually significantly larger, and so more resources are required to parse it.

In your example, struct NAME and struct_alias are indeed equivalent.

struct_alias variable1;
struct NAME variable2;

are correct;

NAME variable3;

is not, as in C the struct keyword is required.

Tags:

C

Struct

Typedef