Learning Objectives
After completing this chapter, you will be able to:
Appreciate the concept of structures and unions
Define and utilize the advantages of structures and unions
Differentiate structures and unions
Declare enumerated variables
Define new data types using typedef statement
Introduction
Structures and Unions are the main constructs available in C by which programmers can define new data type. Structures and unions provide a way to group together logically related data items. Structure
Structure is a derived data type used to represent heterogeneous data items. A structure is an aggregation of components that can be treated as a single variable. The components are called Members.
For example, an employee is represented with the following attributes: employee code (string / integer), employee name (string), department code (string), salary (float).
Declaration and Initialization
Declaration
C provides facilities to define structures via a template and to declare a tag to be associated with such structures so that it is not necessary to repeat the definition. “struct” keyword is used to define structures.
General form: struct tag_name {
type variable-name, variable-name,...; type variable-name, variable-name,...; type variable-name, variable-name,...; :
:
type variable-name, variable-name,...; };
Structure-variables can be declared separately by specifying: struct tag_name new-structure-variable;
When declaring structure variables, a separate instance of structure will be created with the name specified and memory will be allocated for that. Individual members will be given a separate memory location.
Structure definition and declaration of structure variables can be combined together. Here, tag name is optional.
Note: If tag name is not specified in the declaration, no extra structures can be created.
Example 12.1 1) struct employee { int code; char name[20]; int dept_code; float salary; } ;
struct employee emp1, emp2;
2) struct employee (tag name is optional here)
{ int code; char name[20]; int dept_code; float salary; } emp1, emp2; Initialization
Structure variables can be initialized at the time of declaration. The format used is quite similar to initializing an array. If the structure variable is declared before the main function in the global declaration section, the member variables are automatically initialized to zero or Null depending on the data type of the member variable. If it is partially initialized, uninitialized members are assigned zero or Null.
Example 12.2 struct stud { int rollnum; char name[20]; int semester; float avg; };
struct stud stud1={101,”Dina”, 1, 90.78}, stud2={102, “Raja”, 1};
For the structure variable ‘stud2’, the ‘avg’ will be initialized to 0.0
Individual structure members can be initialized only via structure variable. No storage class can be specified for structure members.
struct employee {
int empno = 101 ; illegal;
static char[20] empname = “AAAA”; illegal;
}
Accessing the members
Members of the structure can be accessed by using the member access operator “.”(dot). If ‘s’ is a structure variable with a member named ‘m’, then the expression “s.m” refers to the value of the member ‘m’ within the structure ‘s’.
General Form: struct_vble . member-field-name Example 12.3 emp1.code emp1.name emp1.dept_code emp1.salary emp2.code emp2.name Operations on Structures
Two structure variables cannot be compared for equality, even though the values stored in the member variables are same. This is because, slack bytes are added in-between two member variables and these slack bytes have garbage value. While comparing structure variables, the values in slack bytes are also compared, which is always not same for different structure variables. Assignment operation is allowed. For example, if ‘a’ and ‘b’ are two structure variables of the same structure type, the assignment expression a = b is valid. It causes each member of ‘a’ to be assigned the value of the corresponding member of ‘b’.
sizeof() operator can be used to find the size of the structure. Example 12.4 struct emp { int empno; char name[20]; float basic; } emp1;
printf (“Size = %d”,sizeof(emp1)); Size = 26
Nested Structure
Just as arrays of arrays, structures can contain members that themselves are structures. This can be a powerful method to create complex data types.
Note: Member structure must be defined prior to its use.
Example 12.5 struct date { int day; int month; int year; }; struct employee { int code; char name [20]; struct date doj; int dept_code; float salary; }emp1,emp2;
In this example, if we want to access the year of joining of an employee of emp1, then we can do so by writing:
Structures and Arrays
A structure can be a array of structure and the members of structures can be arrays.
Example 12.6 Array of structures struct stud { int rollnum; char name[20]; int semester; int avg; };
struct stud student[50];
Accessing values: student [1].rollnum student [1].name student [1].semester student [1].avg
Example 12.7: Arrays within structures struct student-mark { int rollnumber; char name[15]; int sub_marks[5]; }student; Accessing values: student.sub_marks[0] student.sub_mark[1]
Structures and Pointers
Structure variable can be declared as pointers. It will be useful when an entire structure is passed to a function via call by reference. Pointer declaration to a structure is as follows:
struct student *ptr;
In this declaration, ‘ptr’ is a pointer type variable, which can hold an address of a variable of the type ‘student’.
Example 12.8 struct stud { int rollnum; char name[20]; int semester; float avg; };
struct stud student={101,”raja”, 1, 95.67}, *ptr ; To make ‘ptr’ to point to the structure ‘student’, we can write as
ptr = &student;
Accessing a member through pointer variable
The notation for referring a member field of a structure pointed by a pointer is as follows:
(*pointer). memberfieldname (OR)
pointer -> memberfieldname
Example 12.9
printf(“ %d \t %s \t %d \t %f “, ptr->rollnum, ptr->name, ptr->semester, ptr->avg);
Self-Referential structures
A structure containing a member that is a pointer to the same structure type is called self- referential structures. It is used to build various kinds of linked data structures.
Example 12.10 struct employee { char name[20]; char gender; float salary;
struct employee *empptr; };
Structures and Functions
Structures can be passed to a function via call by value and call by reference methods. When the structure variable (which not a pointer) is passed as an argument to a function, it is passed using call by value method. All the members are copied into corresponding formal arguments. But changes will not be reflected back.
Example 12.11 struct emp { int empno; char empname[10]; }; main( ) {
void display(struct emp);
struct emp emp1 = { 101 , “AAAA”} ; display(emp1);
}
void display(struct emp emp2) {
printf(“ %d “ , emp2.empno); printf(“ %s “ , emp2.empname);
}
Entire structure can be passed to a function using call by reference method. We can use pointer to structures, or we can pass address of the structure variable using & operator.
Example 12.12 struct emp { int empno; char empname[10]; }; void main( ) {
void change(struct emp *);
struct emp emp1 = { 101 , “AAAA”} ; change(&emp1);
printf(“%d” , emp1->empno); /* prints 102 */ }
{
emp2->empno=102; }
Function can return a structure type
struct_name = fun_name (struct_vble_name);
Function should be declared and defined as:
struct tag_name fun_name( struct tag_name struct_vble_name, …)
Example 12.13
emp1 = emp_pay (wage, x, y); wage is a structure variable of sal structure. emp1 is a structure variable of employee structure. struct employee emp_pay (struct sal pay, int a, float b) { } function definition
Unions
Union, like a structure, is a derived data type. Unions follow the same syntax as structures. The programmer is responsible for interpreting the stored values correctly. Union differs from structure in storage and in initialization.
Declaration
The declaration can be thought of as a template - it creates the type, but no storage is allocated. In the declaration, keyword ‘union’, the tag name, and the members of the union are given. The tag name, along with the keyword ‘union’, can be used to declare variables of the union type. For each variable, the compiler allocates a piece of storage that can accommodate the largest of the specified members.
General Form: union tag_name {
type variable-name, variable-name,...; type variable-name, variable-name,...; type variable-name, variable-name,...; :
:
type variable-name, variable-name,...; }union-variable, union-variable... ;
Initialization
Union can be initialized only with a value for the first union member. No other member can be initialized. Example 12.14 union item { int m; float x; char c; };
static union item product = {100}; /* m will be initialized with 100 */
Accessing the member of union
The notation used to access a member of a union is identical to that used to access member of a structure. The dot operator (.) is used to access the members. Union permits a section of memory to be treated as a variable of one type on one occasion, and as a different variable of a different type on another occasion. Thus, only one member variable can be accessed at a time.
Union of Structures
Structures and unions can be members of structures and unions.
Example 12.15 Union of Structures struct employee_type { int code; char name[20]; int dept_code; float salary; }; struct stud_type { int rollno; char name[15]; int age; float avg; };
union person
{
char surname[10];
struct employee_type e1;
struct stud_type s1;
}ex;
In the above example, the union allows the structure variables, e1 and s1, to share common memory. That is, the user can use either e1 or s1, but not both, at the same time.
The elements of this union of structures are accessed using dot operator as follows: ex.e1.salary
Enumeration
Enumeration is a derived data type, similar to structures or a union. Its members are constants that are written as identifiers, though they have signed integer values. These constants represent values that can be assigned to corresponding enumeration variables. “enum” keyword is used to declare enumerated variables.
General Form:
enum tag { member1 , member2 , …… member n } ;
tag is a name that identifies enumerations having this composition and members represent the identifiers that may be assigned to variables of this type. The member names must differ from one another.
Enumerated variables can be declared as follows:
storage-class enum tag var1 , var2 , ……… var n;
As structures, definition and variable declaration can be combined.
Example 12.16
enum escapes { bell = `\a', backspace = `\b', tab = `\t’, newline = `\n', vtab = `\v', return = `\r'}
main() {
enum escapes e1; e1 = getch(); if (e1 == newline)
printf("newline"); }
Enumeration variables can be processed in the same manner as other integer variables. As with arrays, first enumerated name has index value 0, next value is calculated as previous plus one. We can also override the 0 start value by assigning some other value.
enum colors { red = 1 , blue = 5 , green }
Here, green takes the value 6.
Typedef Statement
The ‘typedef’ allows users to define new data types that are equivalent to existing data types. It is used to give new names to existing data types.
General Form
typedef datatype new-type;
Example 12.17
typedef numbers int;
numbers is the new name given to integer data type and it can be used to declare integer variables.
numbers n1, n2 ; n1 , n2 are the integer variables.
typedef is mostly useful with structures and unions.
Example 12.18 typedef struct { int empno; char empname[10]; }employee;
employee is the name given to the structure of the above type. Then structure variables can be declared as follows,
Summary
Structure is a derived data type used to store heterogeneous data items under a single unit.
Structure members can be accessed by structure variables using dot ( . ) operator.
Structures can be nested and can also have self reference.
Structure can be passed to a function by both call by value approach and call by reference approach.
Unions are similar to structures but the main difference is that union members share the common memory location whereas memory is allocated to individual structure members.
In unions, only one member is accessible at a time.
enum keyword is used to define enumerations.
typedef statement is used to define new data types which are compatible with existing ones.
Test your Understanding
1. What distinguishes an array from a structure?
2. What is a self referential structure and where can it be used? 3. Consider the following structure,
struct {
int a; int *p; }*p1;
How can the content pointed by member pointer p be accessed via structure variable p1?
4. What will be the result when the following code is executed? struct stud_type { int rollno; char name[15]; int age; }; union person { char surname[10]; struct stud_type s1; }ex;
Answers:
1. The elements of an array are always of the same type, whereas the members of a structure can be of different types.
2. Self referential structures will contain a member that is a pointer to the parent structure type. It is very useful in applications that involve linked data structures.
3. *p1->p; 4. Size = 19