1

Why is the following legal:

typedef struct a aType;
struct a
{
   int x;
   aType *b;
};

and the following illegal:

void main()
{
    typedef struct a aType;
    aType someVariable;
    struct a
    {
      int x;
      aType *b;
    };
}

I'm just curious as in each case it is forward referencing and as far as I know, at least for functions and variables, forward referencing is not legal.

Also, would the answer for this be the same for C++ as well?

Jonathan Leffler
  • 666,971
  • 126
  • 813
  • 1,185
Anurag
  • 571
  • 3
  • 16
  • 4
    In case 2, the compiler doesn't know the size of `aType` yet — that appears after you try to define `someVariable`. You could, however, use `aType *somePointer;` legitimately — the pointer size is known even if the size of what it points to is not. – Jonathan Leffler Jan 19 '17 at 20:58
  • 1
    See [What should `main()` return in C and C++?](http://stackoverflow.com/questions/204476/) – Jonathan Leffler Jan 19 '17 at 20:58
  • 1
    Please use a more corresponding title. It is completely unrelated to what you ask. And if you are interested about different languages, ask seperate questions. – too honest for this site Jan 19 '17 at 21:25
  • @JonathanLeffler Function main can have any type in a hosted environment. – 2501 Jan 19 '17 at 21:40
  • @2501: And what makes you think I don't know that? I didn't say it was wrong — I pointed to where there is information about the return type of `main()`. If the code is not running on Windows, using `void main()` is very unlikely to be correct, though. – Jonathan Leffler Jan 19 '17 at 21:43
  • @JonathanLeffler Isn't it theoretically possible to have a different pointer sizes to different types? – Eugene Sh. Jan 19 '17 at 21:53
  • 2
    @EugeneSh.: Yes, but pointers to all `struct` types will have the same size and representation (6.2.5/28). – John Bode Jan 19 '17 at 22:19
  • @JohnBode Thanks. I've suspected this :) – Eugene Sh. Jan 19 '17 at 22:21

2 Answers2

3

This of it this way:

typedef struct a aType;
struct a { int x; aType *b; };

is the same as:

struct a;
typedef struct a aType;
struct a { int x; aType *b; };

So you're forward-declaring a struct, typedefing it and later defining it. Perfectly fine.

Now the second example:

typedef struct a aType;
aType someVariable;
struct a { int x; aType *b; };

This has nothing to do with the fact that it's in local scope. What's happening is this:

struct a;
typedef struct a aType;
aType someVariable; // error: when it gets here, aType is still incomplete
struct a { int x; aType *b; };
aType someVariable; // perfectly fine, aType not incomplete

Remember that compilation happens in order. When you try to declare someVariable the compiler doesn't know what struct a is yet, so it doesn't know its size, hence it doesn't know how much memory to allocate for it, hence a compile error. Declaring it after aType is defined works as expected.

DeiDei
  • 9,225
  • 6
  • 46
  • 69
3

You are allowed to create pointers to incomplete types, because the size of the pointer object does not depend on the size of the pointed-to type. Pointers to different struct types have the same size and representation, regardless of the size of the struct type itself.

You are not allowed to create instances of incomplete types, since the size of the type isn't known.

John Bode
  • 106,204
  • 16
  • 103
  • 178
  • [Your citation](http://stackoverflow.com/questions/41751479/why-are-pointers-to-incomplete-types-allowed-and-not-variables-of-incomplete-typ#comment70698059_41751479) is also useful. – chux - Reinstate Monica Jan 19 '17 at 22:51