Declaring and Defining a Structure

A structure type definition describes the members that are part of the structure. It contains the struct keyword followed by an optional identifier (the structure tag) and a brace-enclosed list of members.

A declaration of a structure data type has the form:

>>-struct--+-identifier--------------------------+-------------><
           |                    .-----------.    |
           |                    V           |    |
           '-+------------+--{----member--;-+--}-'
             '-identifier-'
 
 

The keyword struct followed by an identifier (tag) gives a name to the data type. If you do not provide a tag name, you must put all variable definitions that refer to it within the declaration of the data type.

A structure declaration has the same form as a structure definition except the declaration does not have a brace-enclosed list of members. A structure definition has the same form as the declaration of that structure data type, but ends with a semicolon.

Defining Structure Members

The list of members provides the structure data type with a description of the values that can be stored in the structure. In C, a structure member may be of any type except "function returning T" (for some type T), any incomplete type, any variably modified type, and void. Because incomplete types are not allowed as a structure member, a structure type may not contain an instance of itself as a member, but is allowed to contain a pointer to an instance of itself.

The definition of a structure member has the form of a variable declaration. The names of structure members must be distinct within a single structure, but the same member name may be used in another structure type that is defined within the same scope, and may even be the same as a variable, function, or type name. A member that does not represent a bit field can be of any data type, which can be qualified with either of the type qualifiers volatile or const. The result is an lvalue. However, a bit field without a type qualifier can be declared as a structure member. If the bit field is unnamed, it does not participate in initialization, and will have indeterminate value after initialization.

To allow proper alignment of components, holes or padding may appear between any consecutive members in the structure layout.

Flexible Array Members

The last element of a structure with more than one named member may be an incomplete array type, referred to as a flexible array member.

A flexible array member is an element of a structure with more than one named member. The flexible array member must be the last element of such a structure and must be of an incomplete array type.

>>-array_identifier[ ]-----------------------------------------><
 
 

For example, b is a flexible array member of struct foo.

struct foo{
   int a;
   char b[];
};

The size of struct foo is 4. struct foo cannot be a member of another struct or array.

When the array subscript is zero, the array member is considered a zero-extent array.

>>-array_identifier[0]-----------------------------------------><
 
 

If in the previous example b is declared as a zero-extent array, the size of struct foo is still 4, but struct foo is allowed to be a member of another struct or array, as in the following example.

struct bar{
   struct foo zearray;
};

Usually a flexible array member is ignored. However, it is recognized in two cases:

In the second case, the behavior is as if that member were replaced with the longest array that would not make the structure larger than the object being accessed. The offset of the array remains the same as that of the flexible array member. If the replacement array would have no elements, the behavior is as if it had one element, but that element may not be accessed, nor can a pointer one past it be generated. To illustrate, d is the flexible array member of the structure struct s.

// Assuming the same alignment for all array members,
 
struct s { int n; double d[]; };
struct ss { int n; double d[1]; };
 

The expressions offsetof(struct s, d) and offsetof(struct ss, d) have the same value: sizeof(struct s).

Related References

IBM Copyright 2003