Reputation: 210765
Why is
void foo(T*);
illegal in both C and C++ (because T
is undefined), whereas
void foo(struct T*);
is valid, even though it still does not define T
? Is there any situation in which it makes a semantic difference to the caller whether T
is a struct or some other type (class/enum/typedef/etc.)?
Upvotes: 11
Views: 1974
Reputation: 108986
In C, because pointer to structs (any struct) all have the same width and alignment properties
6.2.5/27 (C99 Standard)
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.
Pointers to anything, on the other hand, may have distinct width and/or alignment properties (void*, function pointers, unsigned char*, ...)
Upvotes: 6
Reputation: 793269
struct T
declares T
as a struct
even when it appears in a larger declaration, i.e. the declaration of foo
. The type is incomplete but that doesn't matter when it's used to declarat a pointer function parameter.
Without the struct
the compiler doesn't know anything about what T
is supposed to be.
If T
had previously been declared as a struct
then void foo(T*)
would be allowed in C++ but not C because the names of struct
s don't automatically become type names although you can declared a typedef
with an identical name in C if you want to.
Upvotes: 1
Reputation: 385405
void foo(struct T*);
simultaneously functions as a forward-declaration of struct T
within that scope, so it's safe to name a pointer to it.
In void foo(T*)
there is no telling what T
is supposed to be. If it turns out to be the name of a variable rather than a type, then the line of code is ill-formed. C++ needs more information before it can say that the line of code is valid.
Upvotes: 6
Reputation: 65649
struct T
acts as a forward declaration of T. You're promising the compiler you'll define it later. If you actually did something on T or tried to instantiate it, you'd have problems:
struct T t1; //error, incomplete type
struct T* t2; // ok
t2->foo // error, incomplete type
Just
T
is an arbitrary identifier. Is it a variable? Is it a function? The language provides no facility to forward declare without adding struct
or class
in front of the variable.
Upvotes: 3