The C language permits structures to be nested, in which a structure can contain structure members. A structure may be declared inside another structure. Also, a structure may be a data member of another structure. The important thing to note is how to initialize the data members of inner structures and how to access the data members of inner structures. The use of such nested structures facilitates representation and processing of complex data.

Declaration of Nested Structures

Consider that we wish to represent the following information of a person: salutation, full name, gender and date of birth. This can be done in a straight-forward way as shown below.

struct person {

char salut[5];

char lname[20], fname[20], mname[20];

char gender;

int dob_dd, dob_mm, dob_yy;

} ;

However, this is an awkward implementation as the date of birth is represented using three fields. This approach will soon be tedious and cluttered if we also wish to store information about more dates. A better way is to use nested structures and define date of birth as a nested structure member as shown below.

struct date {

int dd, mm, yy;

} ;

struct person {

char salut[5];

char lname[20], fname[20], mname[20];

char gender;

struct date dob;

} ;

Observe that the structure date is declared before it is used in structure person to declare member dob.Now consider a variable p of type struct person:

struct person p;

The members of contained structures can be accessed using the usual syntax that involves the use of the dot (.) operator. Thus, the dd, mm and yy fields of the date of birth of this person (p.dob) can be accessed as p.dob. dd,p ,dob ,mm and p.dob. yy, respectively.

It is also possible to declare structure date within the declaration of structure person as shown below.

struct person {

char salut[5];

char lname[20], fname[20], mname[20];

char gender;

struct date {

int dd, mm, yy;

} dob;

} ;

Although structure date is declared inside person, we can subsequently use it to declare members in other structures, structure variables as well as function parameters and return types.

Note that we can also use anonymous structure declaration, i. e., omit the name of the structure as shown below. However, we cannot use this inner structure in subsequent parts of the program.

struct person {

char salut[5];

char lname[20], fname[20], mname[20];

char gender;

struct {

int dd, mm, yy;

} dob;

}

Example of Nested Structures

a) Nested Structures to represent a rectangle

Consider now the representation of a rectangular region on the screen. Although a rectangle has four vertices, we can use a pair of opposite vertices (e.g. top-left and right-bottom)to represent it. Thus, we can declare a structure to represent a rectangle on screen as shown below.

struct rect {

double x1, y1, x2, y2;

} ;

A better approach to declare this structure using nested structures is shown below.

struct point {

double x, y;

} ;

struct rect {

struct point lt, rb; /* top-left & right-bottom corners */

} ;

Note that instead of using x and y coordinates as members, we now declare the rect structure more naturally in terms of the two comer points (i.e., variables of type struct point). Now if we define a variable rl of type struct rect, the x and y coordinates of its top-left comer can be accessed as rl .1t. x and rl. lt. y, respectively.

b) Improve structure to represent a person

Let us again consider the structure person declared above. Observe that a person's name isrepresented using four members (salut, lname, fname and mname).We can further simplify this structure by combining these four name fields in another structure as shown below.

struct date {

int dd, mm, yy;

} ;

struct name {

char salut[S];

char last[20], first[20], middle[20];

} ;

struct person {

struct name name;

char gender;

struct date dob;

};

struct person p;

The name structure, which is used to represent a person's name, declares four members: salut, last, first and middle. The person's name is also referred to in the person structure as name. We could have used some other name for this structure, say person_name. However, the use of the identifier name for the structure as well as the member is quite obvious and such usage is permitted in C. Note that the individual components of a person's 'name (p. name) can be accessed as p. name. last, p. name. first, etc.

Initializing Nested Structures

A nested structure is initialized by using the usual structure initialization syntax for the structure itself as well as for the contained structure members. Thus, in the general format for initialization of a structure given below

struct tag var= { expr1, expr2, ... } ;

we replace the initializer expression, corresponding to a structure member, with a structure initializer list enclosed in braces.

For example consider the improved declaration of structure person in Example that used the structures name and date to represent the person's name and date of birth. We can initialize a variable of this structure as shown below.

Note that other rules for structure initialization are applicable for the initialization of nested structures as well. In addition, we can also omit values for one or more members at the end of each contained structure as well. The compiler will initialize these members with default values. Consider, for example, the initialization statement given below which omits the date of birth and middle name of a character from a popular Hindi movie.

struct person gabbar = { {"", "Singh", "Gabbar"}, 'M'};

The middle name is initialized with a null value and all the components of date of birth are initialized to zero.

Processing Nested Structures

We have already seen that the nested structure members as well as individual members of nested structure members are accessed using the dot (.) operator. The nested structure members can be used as function parameters and return values. Also, the individual members of contained structures can be used in expressions, passed to functions, etc.

Example of Nested Structures

For the sake of illustration, let us consider a simple structure as declared in Program in which the outer structure is struct Employee and the inner structure is struct Salary. The struct Salary by itself does not hold any data value. It is only held by its instance Pay. Similarly in C++, the class object holds the data values and not the class. Therefore, for the outer structure, the instance Pay is a member of struct Employee. The two structures may be declared as shown below.

struct Employee //declaration of outer structure

{

int Age;

struct Salary //declaration of inner structure

{

int Basic_pay;

int Allowances;

} Pay; //end of inner structure

} El, E2; // End of outer structure

The data members of inner structure, i.e., struct Salary may be initialized as below.

E2.Pay.Basic_Pay = 12000;

E2.Pay.Allowances = 2000;

The total emoluments of employee E2 may be obtained as below.

Total emoluments of E2 = E2.Pay.Basic_Pay + E2.Pay.Allowances

Note that the dot selection operator is applied twice both for basic pay and allowances because here E2 is the name of the outer structure instance (some prefer to call instances as structures also). The code E2. Pay selects Pay which is one of the members of the structure. Since Pay is also an instance of structure Salary, a second selection operator is needed to select its members that are basic pay and allowances. Program illustrates this.