Previous: Intertwined Incomplete Types, Up: Structures [Contents][Index]
The name that follows struct
(see Structures), union
(see Unions, or enum
(see Enumeration Types) is called
a type tag. In C, a type tag never conflicts with a variable
name or function name; the type tags have a separate name space.
Thus, there is no name conflict in this code:
struct pair { int a, b; }; int pair = 1;
nor in this one:
struct pair { int a, b; } pair;
where pair
is both a structure type tag and a variable name.
However, struct
, union
, and enum
share the same
name space of tags, so this is a conflict:
struct pair { int a, b; }; enum pair { c, d };
and so is this:
struct pair { int a, b; }; struct pair { int c, d; };
When the code defines a type tag inside a block, the tag’s scope is limited to that block (as for local variables). Two definitions for one type tag do not conflict if they are in different scopes; rather, each is valid in its scope. For example,
struct pair { int a, b; };
void
pair_up_doubles (int len, double array[])
{
struct pair { double a, b; };
…
}
has two definitions for struct pair
which do not conflict. The
one inside the function applies only within the definition of
pair_up_doubles
. Within its scope, that definition
shadows the outer definition.
If struct pair
appears inside the function body, before the
inner definition, it refers to the outer definition—the only one
that has been seen at that point. Thus, in this code,
struct pair { int a, b; };
void
pair_up_doubles (int len, double array[])
{
struct two_pairs { struct pair *p, *q; };
struct pair { double a, b; };
…
}
the structure two_pairs
has pointers to the outer definition of
struct pair
, which is probably not desirable.
To prevent that, you can write struct pair;
inside the function
body as a variable declaration with no variables. This is a
forward declaration of the type tag pair
: it makes the
type tag local to the current block, with the details of the type to
come later. Here’s an example:
void
pair_up_doubles (int len, double array[])
{
/* Forward declaration for pair
. */
struct pair;
struct two_pairs { struct pair *p, *q; };
/* Give the details. */
struct pair { double a, b; };
…
}
However, the cleanest practice is to avoid shadowing type tags.
Previous: Intertwined Incomplete Types, Up: Structures [Contents][Index]