Previous: , Up: Structures   [Contents][Index]


15.20 Type Tags

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: , Up: Structures   [Contents][Index]