2

I was digging into a 3rd party code base and found that it is apparently valid to declare a type as a pointer to an undefined struct. As a minimum working example, consider a C file test.c containing nothing but:

typedef struct foo *bar;

What surprises me is that this file compiles without any problems using the command

gcc test.c -shared

Why does the compiler not complain about the struct foo not being declared anywhere?

My environment is Ubuntu 16.04 with gcc (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609.

Johannes P
  • 888
  • 8
  • 16

2 Answers2

4

The declaration above creates a forward declaration of struct foo. Although you can't access its members, you can operate on a pointer to it.

This is commonly referred to as an opaque type, and is used to hide implementation details of a library from users of the library.

For example a library implementation may contain the following:

lib.c:

struct foo {
  int f1;
};

struct foo *init()
{
    return malloc(sizeof(struct foo));
}

void set1(struct foo *p, int val)
{
    p->f1 = val;
}

int get1(struct foo *p)
{
    return p->f1;
}

void cleanup(struct foo *p)
{
    free(p);
}

The header file for this library might look like this:

lib.h:

struct foo;

struct foo *init(void);
void set1(struct foo *p, int val);
int get1(struct foo *p);
void cleanup(struct foo *p);

The user of this library would use the init function to create an instance of the struct and the set1 and get1 functions to read / update the member. The user can't however create an instance of struct foo or access the members without going through one of the interface functions.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
dbush
  • 205,898
  • 23
  • 218
  • 273
  • But yes that's possible because the pointer to it is same...that's why the forward declaration and all that – user2736738 Nov 10 '17 at 19:14
  • I think I'd actually turn that around, @coderredoc. The fact that all pointers to structure types have the same size *follows* from the fact that C permits declaring incomplete structure types (i.e. with a tag but no body) and deriving pointers to such types. The effect is that the size of structure pointers cannot be a function of the structure members. – John Bollinger Nov 10 '17 at 19:27
  • Ah not it seems circular.. @JohnBollinger: Many a times I have read here the reverse. I guess there is no valid way to know for sure..which drove what – user2736738 Nov 10 '17 at 19:30
  • Perhaps not, @coderredoc, but if I were to try, I would point out that the standard does not, in fact, guarantee that structure pointers are all the same size. That just turns out to be a universal implementation decision. – John Bollinger Nov 10 '17 at 19:42
  • 2
    ISO/IEC 9899:2011 §6.2.5 Types ¶28: _A pointer to `void` shall have the same representation and alignment requirements as a pointer to a character type. Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements. All pointers to structure types shall have the same representation and alignment requirements as each other. All pointers to union types shall have the same representation and alignment requirements as each other. Pointers to other types need not have the same representation or alignment requirements._ – Jonathan Leffler Nov 13 '17 at 02:05
1

Because pointer to structs have same size (for any structs). The size of a structure pointer doesn't depend on it's definition. Because no matter what, the pointer to it would be behaved the same way as any other structures pointer.

user2736738
  • 30,591
  • 5
  • 42
  • 56