user541686
user541686

Reputation: 210765

Why Pointers to Undefined Structs are Sometimes Illegal in C and C++

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

Answers (4)

pmg
pmg

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

CB Bailey
CB Bailey

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 structs don't automatically become type names although you can declared a typedef with an identical name in C if you want to.

Upvotes: 1

Lightness Races in Orbit
Lightness Races in Orbit

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

Doug T.
Doug T.

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

Related Questions