Nested Structures and Arrays in C

In C language it is possible to combine data structures and arrays together. This is one of the strengths of the language, which allows to create complex data structures in a simple way.

Arrays can have a data structure as element type, and data structures can contain other arrays or other data structures.

In this lesson we will see how to combine data structures and arrays in C language.

Nested Structures

It is often convenient to define a data structure that contains other data structures. This type of data structure is called nested structure.

Suppose, for example, we want to create a program that manages teachers and students of a school. For each teacher and for each student, we want to store the name, surname and date of birth. In addition, for each teacher we want to store also the number of lesson hours they teach and for each student we want to store the number of accumulated credits.

To store this information, we can define a data structure that contains the information common to teachers and students, and two data structures that contain the specific information of teachers and students.

struct person {
    char name[20];
    char surname[20];
    int day;
    int month;
    int year;
};

struct teacher {
    struct person personal_data;
    int lesson_hours;
};

struct student {
    struct person personal_data;
    int credits;
};

In this way, if we have defined a variable of type struct teacher or struct student, we can access the information common to teachers and students through the personal_data field.

struct teacher t = {
    .personal_data = {
        .name = "Mario",
        .surname = "Rossi",
        .day = 1,
        .month = 1,
        .year = 1970
    },
    .lesson_hours = 20
};

struct student s = {
    .personal_data = {
        .name = "Luigi",
        .surname = "Verdi",
        .day = 1,
        .month = 1,
        .year = 2002
    },
    .credits = 180
};

printf("Teacher name: %s\n", t.personal_data.name);
printf("Student surname: %s\n", s.personal_data.surname);

In this example, to access the teacher's name we have applied the access operator . twice: the first time to access the personal_data field of the variable t, and the second time to access the name field of the variable t.personal_data.

One of the advantages of using nested data structures lies in the fact that we can, for example, define functions that work on the common part of the structures. Returning to our example, we can define a function that prints the personal data of a person, regardless of whether they are a teacher or a student:

void print_person(struct person p) {
    printf("Name: %s\n", p.name);
    printf("Surname: %s\n", p.surname);
    printf("Date of birth: %d/%d/%d\n", p.day, p.month, p.year);
}

Having done this, we can invoke the function in this way:

print_person(t.personal_data);
print_person(s.personal_data);

The second advantage lies in the fact that we can easily copy a nested structure into another nested structure. For example, if we wanted to copy the personal data of a teacher into another variable of type struct person, we could do it like this:

struct person p = t.personal_data;
Definition

Nested Structures

In C language a nested data structure is a data structure defined inside another data structure.

There is no limit in the language to the number of nesting levels that can be used.

To access the members of a nested structure, it is necessary to use the access operator . to access the fields of the outer structure, and the access operator . to access the fields of the inner structure. The syntax is as follows:

struct inner {
    type inner_member;
};

struct outer {
    struct inner structure_member;
    type outer_member;
};

struct outer variable;

variable.structure_member.inner_member;

Arrays of Structures

One of the most used combinations of arrays and structures is to use arrays that contain data structures. In this way it is possible to create simple databases.

Returning to the previous example, we could store all the information about teachers in an array of structures struct teacher that we will call teachers:

struct teacher teachers[100];

To access a specific teacher within the array, we can use the indexing operator []:

print_person(teachers[0].personal_data);

In this case we have used a combination of indexing operator and access operator to access the personal_data field of the variable teachers[0].

Definition

Arrays of Structures

In C language, an Array of Structures is an array that contains elements of structure type.

The syntax to declare an array of structures is as follows:

struct structure_name {
    type field1;
    type field2;
    ...
};

struct structure_name array_name[size];

Initialization of Arrays of Structures

To initialize an array of structures, we can use the syntax we have seen to initialize a multidimensional array.

Suppose, for example, we want to store in an array of structures a set of Italian cities and the number of their inhabitants. For each city, we can store the name and the number of inhabitants.

struct city {
    char name[20];
    int inhabitants;
};

At this point we can initialize an array of structures struct city that we will call city_list:

struct city city_list[] = {
    {"Rome", 2873000},
    {"Milan", 1356000},
    {"Naples", 967000},
    {"Turin", 870000},
    {"Palermo", 669000},
    {"Florence", 383000},
    {"Bologna", 376000},
    {"Genoa", 585000},
    {"Bari", 326000},
    {"Catania", 315000}
};

Actually, we could have omitted the inner braces, since the initialization of an array of structures is a special case of initialization of a multidimensional array.

struct city city_list[] = {
    "Rome", 2873000,
    "Milan", 1356000,
    "Naples", 967000,
    "Turin", 870000,
    "Palermo", 669000,
    "Florence", 383000,
    "Bologna", 376000,
    "Genoa", 585000,
    "Bari", 326000,
    "Catania", 315000
};

However, it is always preferable to insert the inner braces, in order to make the code clearer.

Definition

Initialization of an Array of Structures

In C language, the initialization of an Array of Structures is a special case of initialization of a multidimensional array.

The syntax is as follows:

struct structure_name {
    type field1;
    type field2;
    ...
};

struct structure_name array_name[] = {
    {value1, value2, ...},
    {value1, value2, ...},
    ...
};

Designated Initializers and Arrays of Structures in C99

Also for arrays of structures it is possible to use the designated initializers introduced by the C99 standard. This allows us to initialize only some fields of the structure, leaving the others to default values.

Returning to the previous example, we can initialize part of the city_list array in this way:

struct city city_list[10] = {
    [1].name = "Milan", [1].inhabitants = 1356000,
    [2].name = "Naples", [2].inhabitants = 967000,
    [4].name = "Palermo",
    [6].inhabitants = 376000
};
Definition

Designated Initializers in C99 and Arrays of Structures

In the C99 standard of C language it is possible to use designated initializers to initialize an array of structures.

The syntax is as follows:

struct structure_name {
    type field1;
    type field2;
    ...
};

struct structure_name array_name[] = {
    [index1].field1 = value1,
    [index1].field2 = value2,
    ...
    [index2].field1 = value1,
    [index2].field2 = value2,
    ...
};