Previous | Table of Contents | Next |
Cs struct type is directly analogous to Pascals record type and to the equivalent data structures in other languages; it is the predecessor of the class type in C++. A structure is a collection of named members (sometimes called fields or elements) of potentially many different types.
One way of thinking about structures is by comparison with arrays. An array is a collection of adjacent elements, all of identical type, referenced by index numbers. A structure, on the other hand, is a collection of elements of various types, more-or-less adjacent, and referenced by name.
The syntax of a structure declaration is
struct tag { type1 member1 ; type2 member2 ; };
Within the braces, the syntax of the declarations of the individual members is identical to the syntax for declaring ordinary variables, except that no storage classes or initializers are present. Of course, the entity being declared is not a set of variables, but rather a template that can be used when declaring later instances of the actual structure. In the template, it is possible to declare several members of the same type at once (by specifying a comma-separated list of declarators following one base type, as shown in the point example next), to use complex declarators representing derived types such as arrays and pointers, and even to specify members that are themselves user-defined data structures.
A structure declaration typically also contains a tag, which is a name for this particular data structure. The tag is used when declaring later variables or functions that work with data structures of the new type so that the template does not have to be repeated each time. Tag names are chosen using the same rules as for ordinary identifiers, but they have their own namespace.
A traditional example of a user-defined data type is one to represent complex numbers. The declaration
struct complex { double re; double im; };
defines a new structure type, to be known by the tag complex. The template says that each instance of the structure will consist of two members, one named re and one named im, both of type double. Another classic example is a structure for representing points in the plane, which might be defined along the lines of
struct point { int x, y; };
The structure definitions here have described the templates for the new user-defined structures and have given them names (tags). After a new type is defined, the next thing to do is to declare some variables of that type. In the case of structures, this can be done in several ways. One is to use the keyword struct plus a struct tag as a type name, like this:
struct complex c1, c2; struct point ll, ur;
Alternatively, variables having the new type can be declared at the same time that the new type is defined, like this:
struct { int x, y; } ul, lr;
The tag is optional in this case and may be omitted if no other identifiers will be declared having the new type.
Naturally, because structures are a general-purpose part of Cs type system, it is possible to declare arrays of structures, and pointers to structures:
struct complex ca[10]; struct point *p1, *p2;
Formally, then, the full syntax of a structure declaration is
struct tag { member-declarations } declarator-list ;
where the tag, brace-enclosed member declaration list, and declarator list are all optional. This is, in fact, the same as the syntax that we have been using for declarations all along, but with the role of the base type filled by the keyword struct, the optional tag, and the optional member declaration. Therefore, yet another way of declaring structures is to define them as typedefs, as well as or instead of giving them tags. For instance, after defining
typedef struct { int x, y; } point_t;
the identifier point_t is a synonym for the new (and otherwise nameless) structure type and enables later declarations of the form
point_t ll, ur;
which do not require the keyword struct.
Structure variables can also be initialized when they are declared; the syntax is similar to array initialization. The initial values for the various members are all enclosed, in order, within braces:
struct complex c3 = {1., 0.}, c4 = {0., 1.};
If a partial initializer list is provided, trailing members are automatically initialized to 0.
Although we have observed a rough similarity between structures and arrays, it is important to note that the members of a structure are not guaranteed to be stored quite adjacently to each other in memory. The compiler may leave holesunnamed, inaccessible memory locationsfor padding between certain members so that all members are aligned appropriately for efficient access. Furthermore, a structure may have padding added at the end so that all elements of an array of structures remain properly aligned. This padding is generally only of concern when attempts are made to match structures to externally imposed data layouts, but it means that the size of a structure (as computed by sizeof) is often greater than the sum of the sizes of its members.
Previous | Table of Contents | Next |