Module 6. Structures and unions

Lesson 17

STRUCTURES AND UNIONS

17.1  Structures

Recall that the arrays are used to store a large set of data as well as to manipulate these data. However, there is a limitation with the arrays that all the elements stored in an array are to be of the same data type! If you need to use a collection of items with different data types, it is not possible using an array. Instead, a structure is used.

A structure can be considered as a template used for defining a collection of variables under a single name. Structures facilitate a programmer to group several elements of different data types into a single logical unit. Thus, a structure is a collection of one or more variables, possibly of different data types, grouped together under a single name for convenient handling.  

The general syntax of structure is:

struct tag_name

{

data type member1;

data type member2;

. . .

};

For example, let us store a date inside a ‘C’ programme. This can be defined as a structure called date with three elements: day, month and year as follows: 

struct date

{

int day;

int month;

int year;

};

An illustration

The following code segment demonstrates the structure named lib_book (i.e., a collection of library books), which includes members as title (book title), author1 (first author), author2 (second author), ac_no (book accession number), pub_name (publisher’s name), pages (number of pages of the book) and price (unit price of the book in rupees). Note that the data types of the structure members are different unlike an array variable. 

struct lib_books

{

char title[20];

char author1[15];

char author2[15];

char ac_no[10];

char pub_name[20];

int pages;

float price;

           };

The keyword struct declares a structure to hold the details of six fields as described above. The tag name (lib_books) is used to define a data object, ‘library books’ comprising of several members. Hence, the above defined structure is not a variable but a template for the object.  ‘C’ allows a programmer to store both simple as well as sophisticated data types within an array, i.e., a programmer-defined structure can be an element of an array.

Generally, a structure is defined at the beginning of a programme, i.e., just following the main() statement. However, the structure definition statement merely instructs the compiler that a structure exists, but it does not assign any memory to the variable. The memory allocation takes place only when a structure variable is declared. We can declare structure variables using the tag name anywhere in the programme. For example, the statement:

struct lib_books book1,book2,book3;

declares book1, book2 and book3 as variables of the type struct lib_books; each declaration has four elements of the structure lib_books. The complete structure declaration looks like:

struct lib_books

{

char title[20];

char author1[15];

char author2[15];

char ac_no[10];

char pub_name[20];

int pages;

float price;

};

struct lib_books, book1, book2, book3;

A structure does not occupy any memory until it is associated with the structure variable such as book1. The template is terminated with a semicolon. While the entire declaration is considered as a statement, each member is declared independently for its name and type in a separate statement inside the template. The tag name such as lib_books is used to declare structure variables of this data type later in the programme.

Also, both the template declaration as well as the variables’ declaration can be combined in a single statement as follows:

struct lib_books

{

char title[20];

char author1[15];

char author2[15];

char ac_no[10];

char pub_name[20];

int pages;

float price;

} book1, book2, book3;

The use of tag name is optional, e.g., see the following code segment:

struct

{

char title[20];

char author1[15];

char author2[15];

char ac_no[10];

char pub_name[20];

int pages;

float price;

} book1, book2, book3;

The variables, book1, book2 and book3 represent structure variables signifying three books, but the declaration statement does not include a tag name! A structure is usually defined prior to main function along with macro definitions. In such cases, the structure assumes global status and all the functions can access the structure.

17.2  Giving Values to the Members

As stated earlier, the members themselves are not variables, however, they should be linked to structure variables so as to make them meaningful members. The link between a member and a variable is established using the member operator, ‘.’, which is known as dot operator or period operator, e.g., book1.price is the variable representing the price of book1 and can be treated like any other ordinary variable. Let us make use of the scanf statement to assign values as described below:

scanf(“%s”, book1.file);

scanf(“%d”,&book1.pages);

Alternatively, you can assign variables to the members of book1 as follows:

strcpy(book1.title, “basic”);

strcpy(book1.author, “A. K. Sharma”);

book1.pages=187;

book1.price=200.00;

17.3  Initialising structure

Like other data types, you can initialise structure while declaring the same. The structure construct obeys the same set of rules as arrays. Thus, the fields of a structure are initialised by declaring the structure with a list containing values for each field as for arrays. This is demonstrated with the help of following examples.

Example 1: The following code demonstrates the use of structure construct including the structure definition, inputting and storing data into the memory and retrieving information from the memory.

#include <stdio.h>

void main()

{

struct students

{

int id;

char name[20];

char address[20];

char stream[3];

int age;

} newstudents;

printf("Input the Students Information:\n\n");

printf("The student identification number  ");

scanf(" %d",&newstudents.id);

printf("The name of the student  ");

scanf(" %s",&newstudents.name);

printf("The mailing address of the student  ");

scanf(" %s",&newstudents.address);

printf("The stream to which the student belongs  ");

scanf(" %s",&newstudents.stream);

printf("The age (in years) of the student  ");

scanf(" %d",&newstudents.age);

printf("\n\n");

printf("Output Students Information:  \n\n");

printf("Student Identity Number = %d\n", newstudents.id);

printf("Student Name = %s\n", newstudents.name);

printf("Student Address = %s\n", newstudents.address);

printf("Student Stream = %s\n", newstudents.stream);

printf("Age (in years) of Student = %d\n", newstudents.age);

}

The input data fed through the keyboard and the output produced (verbatim) when the above code was executed, are given  below:

Input the Students Information:

The student identification number  009

The name of the student  Aashish

The mailing address of the student  8,Def.Col.,Ambala

The stream to which the student belongs  E

The age (in years) of the student  19

Output Students Information:

Student Identity Number = 9

Student Name = Aashish

Student Address = 8,Def.Col.,Ambala

Student Stream = E

Age (in years) of Student = 19

17.4  Structures Containing Arrays

There can also be structures containing arrays as its elements. This is illustrated with the help of the following example.

Example 2: The following code demonstrates the use of ‘structure’ construct including the structure definition, initialisation the structure with data and retrieving information from the structure.

#include <stdio.h>

void main()

{

struct students

{

int id;

char name[20];

char address[20];

char stream[3];

int age;

};

struct students newstudents = {9, "Aashish", "HEC College","CE", 19};

printf("\n\n");

printf("Output Students Information:  \n\n");

printf("Student Identity Number = %d\n", newstudents.id);

printf("Student Name = %s\n", newstudents.name);

printf("Student Address = %s\n", newstudents.address);

printf("Student Stream = %s\n", newstudents.stream);

printf("Age (in years) of Student = %d\n", newstudents.age);

}

Output Students Information:

Student Identity Number = 9

Student Name = Aashish

Student Address = HEC College

Student Stream = CE

Age (in years) of Student = 19

As stated earlier, an array can contain a structure as one of its elements. Referencing an element in the array containing a structure as an element is quite simple. Also, initialisation of structure arrays is similar to initialisation of multidimensional arrays. Do not confuse this concept with array of structures.

17.5  Arrays of Structure

It is possible to define an array of structures, for example, if you are maintaining information about students of a college and there are 100 students studying in the college. You need to use an array rather than simple variables. You can define an array of structures as shown in following code that demonstrates the use of ‘structure’ construct including the structure definition, initialisation, the structure with multiple data records and retrieving information from the structure:

// Code demonstrating use of a structure

#include <stdio.h>

void main()

{

struct students

{

int id;

char name[20];

char address[20];

char stream[3];

int age;

};

struct students newstudents[] = {

{9, "Aashish", "HEC College", "CSE", 19},

{10,"Anuj","HEC College","EE",19},

{11, "Manpreet", "SPCET", "CE",19}

                                };

printf("\n\n");

printf("Output Students Information:  \n\n");

for (int i=0; i<3; i++)

{

printf("Student Identity Number = %d\n", newstudents[i].id);

printf("Student Name = %s\n", newstudents[i].name);

printf("Student Address = %s\n", newstudents[i].address);

printf("Student Stream = %s\n", newstudents[i].stream);

printf("Age (in years) of Student = %d\n\n", newstudents[i].age);

}

}

Output Students Information:

Student Identity Number = 9

Student Name = Aashish

Student Address = PEC College

Student Stream = CSE‼

Age (in years) of Student = 19

 

Student Identity Number = 10

Student Name = Anuj

Student Address = HEC College

Student Stream = EE

Age (in years) of Student = 19

 

Student Identity Number = 11

Student Name = Manpreet

Student Address = SPCET

Student Stream = CE

Age (in years) of Student = 19

17.6  Structures and Functions

A structure can be passed as an argument to functions. Unlike array names, which always point to the start of the array, structure names are not pointers. Thus, if a change is made to the structure parameter(s) inside a function, the corresponding arguments remain unaffected.

Passing structure to elements to functions

A structure may be passed into a function as individual member or a separate variable. The following programme illustrates as to how to display the contents of a structure by passing its individual elements to a function.

# include <stdio.h>

display(int e_no, char e_name[25], float e_sal);

void main()

{

  struct employee

  {

     int emp_id;

     char name[25];

     char dept[10];

     float salary;

  };

  struct employee emp1 = {267,"Aashish","CSE", 50000.00};

  display(emp1.emp_id, emp1.name, emp1.salary);

}

 

// function to display structure variables

 

display(int e_no, char e_name[25], float e_sal)

  {

    printf(" %d %s %f ", e_no, e_name, e_sal);

    return 0;

  }

The programme output is given below:

Output:

267 Aashish 50000.000000

In this example, the structure members, emp_id, name and salary have been declared as integer type variable, character type array variable and floating-point variable, respectively.

Now, the display function is called using statement,

 display(emp1.emp_id,emp1.name,emp1.salary);

 

i.e., the structure members, emp_id, name and salary are transmitted to the display function. Evidently, passing individual members would become more tedious as the number of structure elements go on increasing; hence, a better way would be to pass the entire structure at a time. This is illustrated with the help of the following programme:

#include <stdio.h>

display(struct employee empf);

struct employee

{

int emp_id;

char name[25];

char dept[10];

float salary;

};

void main()

{

struct employee emp1={12,"Aashish","Computer",75000.00};

//sending entire employee structure

display(emp1);

}

//function to pass entire structure variable

display(struct employee empf)

{

printf("%d %s %s %f", empf.emp_id, empf.name, empf.dept, empf.salary);

return 0;

}

12 Sadanand Computer 7500.000000

17.7  Unions

A union is a variable, which may hold members of different sizes and types. The union, like structure, contains members whose individual data types may differ from each other. However, the members that compose a union all share the same storage area within the computer’s memory whereas each member within a structure is assigned its own unique storage area. Thus, union is used to conserve memory. It is useful for applications involving multiple members where values are not assigned to all the members at any one point of time. Like structure, union can be declared using the keyword union as follows:

union item

{

int m;

float p;

char c;

} code;

This declares a variable, code of the type union item. The union contains three members each with a different data type. However, only one of them can be used at a time. This is because only one location is allocated for union variable irrespective of size. The compiler allocates a piece of storage that is large enough to access a union member; the same syntax is used to access union members as structure members. That is, code.m, code.p and code.c are all valid member variables. While accessing such member variables, it should be ensured that an access is being made to the member whose value is currently stored. For example a statement such as

code.m=456;

code.p=456.78;

Printf(“%d”,code.m);

would produce erroneous result.

Actually, a union creates a storage location that can be used by one of its members at a time. When a different number is assigned a new value, the new value supersedes the previous member’s value. The union may be used in any situations where an application of the structure is possible.

# include <stdio.h>
main( ){
union
{
    int one;
    char two;
} val;
val.one = 300;
printf(“val.one = %d \n”, val.one);
printf(“val.two = %d \n”, val.two);
}

In the above code, there are two members: int one and char two. The member one is initialised to 300. Note that only one member the union has been initialised; however, using two different printf statements, the individual members of the union val are displayed as:

val. one = 300
val. two = 44

Since the char variable two was not initialised, the second printf statement produces a random value of 44.

While using a union, the programmer should keep track of whatever type is put into it and retrieve the right type at the right time. Here’s another example:

#include <stdio.h>

#include <stdlib.h>

main(){

      union {

              float u_f;

              int u_i;

      }var;

      var.u_f = 23.5;

      printf("value is %f\n", var.u_f);

      var.u_i = 5;

      printf("value is %d\n", var.u_i);

      exit(EXIT_SUCCESS);

}

Output

value is 23.500000

value is 5