Nick
Nick

Reputation: 2871

Any way in C to forward declare struct in header without having to use pointer in other files?

Suppose I have this in list.h:

typedef struct list_t list_t;
typedef struct list_iter_t list_iter_t;
list_iter_t iterator(list_t *list);

and then define them in list.c:

typedef struct node_t {
    ...
} node_t;

struct list_iter_t {
    node_t *current;
    // this contains info on whether the iterator has reached the end, etc.
    char danger;
};

struct list_t {
    ...
}

list_iter_t iterator(list_t *list) {
    list_iter_t iter;
    ...
    return iter;
}

Is there anything I can do aside from including the struct declaration in the header file so that in some file test.c I can have:

#include "list.h"

void foo(list_t *list) {
    list_iter_t = iterator(list);
    ...
}

Like maybe tell the compiler the storage size of list_iter_t somehow? It's inconvenient to have to use a pointer (not because it's a pointer, but for other reasons), but at the same time I would like to hide the implementation details as much as possible.

Upvotes: 1

Views: 6114

Answers (2)

caf
caf

Reputation: 239371

It is possible to tell the compiler the size of the structure, using a dummy definition like:

struct node_t {
    char dummy[sizeof(struct { ... })];
};

(with the proper definition instead available to the implementation file).

Formally this causes undefined behaviour; it is likely to somewhat work in practice, though.

You are probably best off just including the proper structure definition though, and leaving a comment to the effect that code should simply not touch the internal members.

Upvotes: 1

Jonathan Leffler
Jonathan Leffler

Reputation: 755114

The succinct answer is "No".

The way you tell the compiler the size of a struct is by telling it the details of how the struct is structured. If you want to allocate an object, rather than a pointer to the object, the compiler must know the complete type of the object. You also can't access the members of a structure via a pointer to the structure if the type is incomplete. That is, the compiler must know the offset and type of the member to generate the correct code to access someptr->member (as well as to allocate somevalue or access somevalue.member).

Upvotes: 3

Related Questions