chapter complete on structure and union with examples of array_compressed
chapter complete on structure and union with examples of array_compressed
UNIT STRUCTURE
8.0 Objectives
8.1 Introduction to Structure
8.1.1 Definition of Structure
8.1.2 Declaration of Structure
8.1.3 Initialization of Structure
8.1.4 Nested Structure
8.1.5 Array of Structure
8.1.6 Self Refrential structure
8.1.7 passing Structure to function
8.1.8 Function as return type as structure
8.1.9 Structures and Pointers
8.2 Union
8.3 Difference between Structure and Union
8.4 Enumerated Data types
8.5 Bit Fields
8.6 Summary
8.7 Questions for Exercises
8.8 Suggested Readings
8.0 Objectives
After going through this unit you should be able to :
understand the concept of Structure
Define and declare a structure variable
Implementation of arrays in structures •
use pointer for structure variable
understand the concept and use of Union
Differentiate between Union and structure
do bitwise manipulation
understand the concept of enumerated data type
char name[64];
char course[128];
int age;
int year;
are some examples of members.
2. Name given to structure is called as tag
student
3. Structure member may be of different data type including user defined data-type also
typedef struct {
char name[64];
char course[128];
book b1;
int year;
} student;
Here book is user defined data type.
C Structure is a collection of different data types which are grouped together and each element in a C structure is called
member.
A normal C variable can hold only one data of one data type at a time.
An array can hold group of data of same data type.
A structure can hold group of data of different data types and Data types can be int, char, float, double and long
double etc.
struct student
{
int a;
char b[10];
Syntax }
a = 10;
Example b = “Hello”;
C Variable:
Syntax: int a;
int Example: a = 20;
Syntax: char b;
char Example: b=’Z’;
C Array:
Syntax: Syntax:
struct tag_name struct tag_name
{ {
data type var_name1; data type var_name1;
data type var_name2; data type var_name2;
data type var_name3; data type var_name3;
}; };
Example: Example:
struct student struct student
{ {
int mark; int mark;
char name[10]; char name[10];
float average; float average;
}; };
#include <stdio.h>
#include <string.h>
struct student
{
int id;
char name[20];
float percentage;
};
int main()
{
struct student record = {0}; //Initializing to null
record.id=1;
strcpy(record.name, "Raju");
record.percentage = 86.5;
struct tag
data_type1 member1;
data_type2 member2;
data_type3 member3;
};
struct <structure_name>
{
structure_Element1;
structure_Element2;
structure_Element3;
...
...
};
Some Important Points Regarding Structure in C Programming :
struct date
{
int date;
char month[20];
int year;
}today;
struct date
{
int date;
char month[20];
int year;
};
struct Book
{
int pages;
char name[20];
int year;
}book1,book2,book3;
We can declare multiple variables separated by comma directly after closing curly.
struct student
{
char name[20];
int roll;
float marks;
}std1 = { "Pritesh",67,78.3 };
In the above code snippet, we have seen that structure is declared and as soon as after declaration we have initialized the
structure variable.
std1 = { "Pritesh",67,78.3 }
This is the code for initializing structure variable in C programming
Way 2 : Declaring and Initializing Multiple Variables
struct student
{
char name[20];
int roll;
float marks;
}
std1 = {"Pritesh",67,78.3};
std2 = {"Don",62,71.3};
In this example, we have declared two structure variables in above code. After declaration of variable we have initialized
two variable.
std1 = {"Pritesh",67,78.3};
std2 = {"Don",62,71.3};
Way 3 : Initializing Single member
struct student
int mark1;
int mark2;
int mark3;
} sub1={67};
Though there are three members of structure,only one is initialized , Then remaining two members are initialized with
Zero. If there are variables of other data type then their initial values will be –
integer 0
float 0.00
char NULL
Way 4 : Initializing inside main
struct student
{
int mark1;
int mark2;
int mark3;
};
void main()
{
struct student s1 = {89,54,65};
- - - - --
- - - - --
- - - - --
};
When we declare a structure then memory won’t be allocated for the structure. i.e only writing below declaration statement
will never allocate memory
struct student
{
int mark1;
int mark2;
int mark3;
};
We need to initialize structure variable to allocate some memory to the structure.
struct student s1 = {89,54,65};
Nested structure in C is nothing but structure within structure. One structure can be declared inside other structure as we
declare structure members inside a structure.The structure variables can be a normal structure variable or a pointer
variable to access the data.
This program explains how to use structure within structure in C using normal variable. “student_college_detail’ structure
is declared inside “student_detail” structure in this program. Both structure variables are normal structure variables.
Please note that members of “student_college_detail” structure are accessed by 2 dot(.) operator and members of
“student_detail” structure are accessed by single dot(.) operator.
#include <stdio.h>
#include <string.h>
struct student_college_detail
{
int college_id;
char college_name[50];
};
struct student_detail
{
int id;
char name[20];
float percentage;
// structure within structure
struct student_college_detail clg_data;
}stu_data;
int main()
{
struct student_detail stu_data = {1, "Raju", 90.5, 71145,
"Anna University"};
printf(" Id is: %d \n", stu_data.id);
printf(" Name is: %s \n", stu_data.name);
printf(" Percentage is: %f \n\n", stu_data.percentage);
struct date
{
int date;
int month;
int year;
};
struct Employee
{
char ename[20];
int ssn;
float salary;
struct date doj;
}emp1;
Accessing Nested Elements :
struct Employee
{
char ename[20];
int ssn;
float salary;
struct date
{
int date;
int month;
int year;
}doj;
}emp1;
Accessing Nested Members :
Example :8.1.4.2
#include <stdio.h>
struct Employee
{
char ename[20];
int ssn;
float salary;
struct date
{
int date;
int month;
int year;
}doj;
}emp = {"Pritesh",1000,1000.50,{22,6,1990}};
return 0;
}
Output :
Employee Name : Pritesh
Employee SSN : 1000
Employee Salary : 1000.500000
Employee DOJ : 22/6/1990
Structure is used to store the information of One particular object but if we need to store such 100 objects then Array of
Structure is used.
Example 8.1.5:
struct Bookinfo
{
char[20] bname;
int pages;
int price;
}Book[100];
Explanation :
Book[1].pages
Live Example : 8.1.5.2
#include <stdio.h>
struct Bookinfo
{
char[20] bname;
int pages;
int price;
}book[3];
int main(int argc, char *argv[])
{
int i;
for(i=0;i<3;i++)
{
printf("\nEnter the Name of Book : ");
gets(book[i].bname);
printf("\nEnter the Number of Pages : ");
scanf("%d",book[i].pages);
printf("\nEnter the Price of Book : ");
scanf("%f",book[i].price);
}
printf("\n--------- Book Details ------------ ");
for(i=0;i<3;i++)
{
printf("\nName of Book : %s",book[i].bname);
printf("\nNumber of Pages : %d",book[i].pages);
printf("\nPrice of Book : %f",book[i].price);
}
return 0;
}
Output of the Structure Example:
#include<stdio.h>
#include<conio.h>
struct Employee
{
int ssn;
char ename[20];
char dept[20];
}emp[3];
//---------------------------------------------
void main()
{
int i,sum;
Here, name is a pointer which points to a structure type and is also an element of the same structure.
Example 8.1.6
struct element
{
char name{20};
int num;
struct element * value;
}
Example :
#include<stdio.h>
#include<conio.h>
//-------------------------------------
struct Example
{
int num1;
int num2;
}s[3];
//-------------------------------------
void accept(struct Example *sptr)
{
printf("\nEnter num1 : ");
scanf("%d",&sptr->num1);
printf("\nEnter num2 : ");
scanf("%d",&sptr->num2);
}
//-------------------------------------
void print(struct Example *sptr)
{
printf("\nNum1 : %d",sptr->num1);
printf("\nNum2 : %d",sptr->num2);
}
//-------------------------------------
void main()
{
int i;
clrscr();
for(i=0;i<3;i++)
accept(&s[i]);
for(i=0;i<3;i++)
print(&s[i]);
getch();
}
Output :
Enter num1 : 10
Enter num2 : 20
Enter num1 : 30
Enter num2 : 40
Enter num1 : 50
Enter num2 : 60
Num1 : 10
Num2 : 20
Num1 : 30
Num2 : 40
Num1 : 50
Num2 : 60
In C, structure can be passed to functions by two methods:
If structure is passed by value, changes made to the structure variable inside the function definition does not reflect in the
originally passed structure variable.
C program to create a structure student, containing name and roll and display the information.
#include <stdio.h>
struct student
{
char name[50];
int roll;
};
void display(struct student stu);
// function prototype should be below to the structure declaration otherwise compiler shows error
int main()
{
struct student stud;
printf("Enter student's name: ");
scanf("%s", &stud.name);
printf("Enter roll number:");
scanf("%d", &stud.roll);
display(stud); // passing structure variable stud as argument
return 0;
}
void display(struct student stu){
printf("Output\nName: %s",stu.name);
printf("\nRoll: %d",stu.roll);
}
Output
If structure is passed by reference, changes made to the structure variable inside function definition reflects in the
originally passed structure variable.
C program to add two distances (feet-inch system) and display the result without the return statement.
#include <stdio.h>
struct distance
{
int feet;
float inch;
};
void add(struct distance d1,struct distance d2, struct distance *d3);
int main()
{
struct distance dist1, dist2, dist3;
printf("First distance\n");
printf("Enter feet: ");
scanf("%d", &dist1.feet);
printf("Enter inch: ");
scanf("%f", &dist1.inch);
printf("Second distance\n");
printf("Enter feet: ");
scanf("%d", &dist2.feet);
printf("Enter inch: ");
scanf("%f", &dist2.inch);
//passing structure variables dist1 and dist2 by value whereas passing structure variable dist3 by reference
printf("\nSum of distances = %d\'-%.1f\"", dist3.feet, dist3.inch);
return 0;
}
void add(struct distance d1,struct distance d2, struct distance *d3)
{
//Adding distances d1 and d2 and storing it in d3
d3->feet = d1.feet + d2.feet;
d3->inch = d1.inch + d2.inch;
First distance
Enter feet: 12
Enter inch: 6.8
Second distance
Enter feet: 5
Enter inch: 7.5
But, dist3 is passed by reference ,i.e, address of dist3 (&dist3) is passed as an argument.
Due to this, the structure pointer variable d3 inside the add function points to the address of dist3 from the
calling main function. So, any change made to the d3 variable is seen in dist3 variable in main function.
int main()
{
complex n1, n2, temp;
printf("For 1st complex number \n");
printf("Enter real and imaginary part respectively:\n");
scanf("%f %f", &n1.real, &n1.imag);
return 0;
}
return(temp);
}
Output
This function computes the sum and returns the structure variable temp to the main() function.
Structures can be created and accessed using pointers. A pointer variable of a structure can be created as below:
struct name {
member1;
member2;
};
int main()
#include <stdio.h>
int age;
float weight;
};
int main()
scanf("%d",&(*personPtr).age);
scanf("%f",&(*personPtr).weight);
printf("Displaying: ");
printf("%d%f",(*personPtr).age,(*personPtr).weight);
return 0;
In this example, the pointer variable of type struct person is referenced to the address of person1. Then, only the structure
member through pointer can can accessed.
#include <stdio.h>
#include <stdlib.h>
struct person {
int age;
float weight;
char name[30];
};
int main()
{
int i, num;
scanf("%d", &num);
// Above statement allocates the memory for n structures with pointer personPtr pointing to base address */
printf("Displaying Infromation:\n");
return 0;
Output
Enter number of persons: 2
Adam
3.2
Eve
2.3
Displaying Information:
Adam 2 3.20
Eve 6 2.30
Union
Union, like structures, contain members whose individual data types may differ from one another. 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, unions are used to conserve memory.
In general terms, the composition of a union may be defined as
union tag{
member1;
member 2;
---
member m
};
Where union is a required keyword and the other terms have the same meaning as in a structure definition.
Individual union variables can then be declared as storage-class union tag variable1, variable2, -----, variable n;
where storage-class is an optional storage class specifier, union is a required keyword, tag is the name that
appeared in the union definition and variable 1, variable 2, variable n are union variables of type tag.
The two declarations may be combined, just as we did in the case of structure. Thus, we can write
Here we have two union variables, purse and belt, of type code.
Each variable can represent either a 5–character string (color) or an integer quantity (size) of any one time.
structure union
Within a structure all members gets memory For a union compiler allocates the memory
allocated and members have addresses that for the largest of all members and in a union
increase as the declarators are read left-to- all members have offset zero from the base,
right. That is, the members of a structure all the container is big enough to hold the
begin at different offsets from the base of the WIDEST member, and the alignment is
structure. The offset of a particular member appropriate for all of the types in the union.
corresponds to the order of its declaration; When the storage space allocated to the
the first member is at offset 0. The total size union contains a smaller member, the extra
of a structure is the sum of the size of all the space between the end of the smaller member
members or more because of appropriate and the end of the allocated memory remains
alignment. unaltered.
Within a structure all members gets memory While retrieving data from a union the type
allocated; therefore any member can be that is being retrieved must be the type most
retrieved at any time. recently stored. It is the programmer's
responsibility to keep track of which type is
currently stored in a union; the results are
implementation-dependent if something is
stored as one type and extracted as another.
One or more members of a structure can be A union may only be initialized with a value
initialized at once. of the type of its first member; thus
union u described above (during example
declaration) can only be initialized with an
integer value.
C provides a capability that enables you to assign an alternate name to a data type.This is
done with a statement known as typedef.The statement
defines the name Counter to be equivalent to the C data type int.Variables can subsequently be declared to be of type
Counter, as in the following statement:
Counter j, n;
The C compiler actually treats the declaration of the variables j and n, shown in the
preceding code, as normal integer variables.The main advantage of the use of the
typedef in this case is in the added readability that it lends to the definition of the
variables. It is clear from the definition of j and n what the intended purpose of these
variables is in the program.
In many instances, a typedef statement can be equivalently substituted by the appropriate #define statement. For example,
you could have instead used the statement
to achieve the same results as the preceding statement. However, because the typedef is
handled by the C compiler proper, and not by the preprocessor, the typedef statement
provides more flexibility than does the #define when it comes to assigning names to
derived data types.
Note that, in this case, Linebuf could not have been equivalently defined with a #define
preprocessor statement.
To declare a variable to be of type enum primaryColor, you again use the keyword enum, followed by the enumerated type
name, followed by the variable list. So the statement
the value 1 is assigned to thisMonth (and not the name february) because it is the second identifier listed inside the
enumeration list.
If you want to have a specific integer value associated with an enumeration identifier,
the integer can be assigned to the identifier when the data type is defined. Enumeration
identifiers that subsequently appear in the list are assigned sequential integer values
beginning with the specified integer value plus 1. For example, in the definition
an enumerated data type direction is defined with the values up, down, left, and
right.The compiler assigns the value 0 to up because it appears first in the list; 1 to
down because it appears next; 10 to left because it is explicitly assigned this value; and
11 to right because it appears immediately after left in the list.
Example
Program 14.1 Using Enumerated Data Types
// Program to print the number of days in a month
#include <stdio.h>
int main (void)
{
enum month { january = 1, february, march, april, may, june,
july, august, september, october, november, december };
enum month aMonth;
int days;
printf (“Enter month number: “);
scanf (“%i”, &aMonth);
switch (aMonth ) {
case january:
case march:
case may:
case july:
case august:
case october:
case december:
days = 31;
break;
case april:
case june:
case september:
case november:
days = 30;
break;
case february:
days = 28;
break;
default:
printf (“bad month number\n”);
days = 0;
break;
}
if ( days != 0 )
printf (“Number of days is %i\n”, days);
if ( amonth == february )
printf (“...or 29 if it’s a leap year\n”);
return 0;
}
Output
Enter month number: 5
Number of days is 31
Output (Rerun)
Enter month number: 2
Number of days is 28
...or 29 if it’s a leap year
Enumerated type definitions behave like structure and variable definitions as far as
their scope is concerned: Defining an enumerated data type within a block limits the
scope of that definition to the block. On the other hand, defining an enumerated data
type at the beginning of the program, outside of any function, makes the definition
global to the file.
BIT FIELDS
The C language was basically developed with systems programming applications in mind. Pointers are the perfect case in
point because they give the programmer an enormous amount of control over and access into the computer’s memory.
Along these same lines, systems programmers frequently must get in and “twiddle with the bits” of particular computer
words. C provides a host of operators specifically designed for performing operations on individual bits.
On most
computer systems, a byte consists of eight smaller units called bits.A bit can assume either
of two values: 1 or 0. So a byte stored at address 1000 in a computer’s memory, for
example, might be conceptualized as a string of eight binary digits as shown:
01100100
The rightmost bit of a byte is known as the least significant or low-order bit, whereas the
leftmost bit is known as the most significant or high-order bit. If you treat the string of bits
as an integer, the rightmost bit of the preceding byte represents 20 or 1, the bit immediately to its left represents 21 or 2, the
next bit 22 or 4, and so on.Therefore, the preceding binary number represents the value 2 2 + 25 + 26 = 4 + 32 + 64 = 100
decimal.
The representation of negative numbers is handled slightly differently. Most computers represent such numbers using a so-
called “twos complement” notation. Using this notation, the leftmost bit represents the sign bit. If this bit is 1, the number
is negative; otherwise, the bit is 0 and the number is positive.The remaining bits represent the value of the number. In twos
complement notation, the value –1 is represented by all bits being equal to 1:
11111111
A convenient way to convert a negative number from decimal to binary is to first add 1
to the value, express the absolute value of the result in binary, and then “complement” all
the bits; that is, change all 1s to 0s and 0s to 1s. So, for example, to convert -5 to binary,
1 is added, which gives -4; 4 expressed in binary is 00000100, and complementing the
bits produces 11111011.
To convert a negative number from binary back to decimal, first complement all of the bits, convert the result to decimal,
change the sign of the result, and then subtract 1. Given this discussion about twos complement representation, the largest
positive number that can be stored into n bits is 2n–1–1. So in eight bits, you can store a value up to 27 – 1, or 127.
Similarly, the smallest negative number that can be stored into n bits is –2n–1, which in an eight-bit byte comes to –128.
On most of today’s processors, integers occupy four contiguous bytes, or 32 bits, in the computer’s memory.The largest
positive value that can, therefore, be stored into such
an integer is 231–1 or 2,147,483,647, whereas the smallest negative number that can be
stored is –2,147,483,648.
Bit Operators
Now that you have learned some preliminaries, it’s time to discuss the various bit operators that are available.The operators
that C provides for manipulating bits are presented in Table
Bitwise ANDing is frequently used for masking operations.That is, this operator can
be used to easily set specific bits of a data item to 0. For example, the statement
w3 = w1 & 3;
assigns to w3 the value of w1 bitwise ANDed with the constant 3.This has the effect of
setting all of the bits in w3, other than the rightmost two bits, to 0, and of preserving the
rightmost two bits from w1.
As with all binary arithmetic operators in C, the binary bit operators can also be used
as assignment operators by tacking on an equal sign. So the statement
word &= 15;
performs the same function as
word = word & 15;
and has the effect of setting all but the rightmost four bits of word to 0.
When using constants in performing bitwise operations, it is usually more convenient
to express the constants in either octal or hexadecimal notation.
Bitwise Inclusive-ORing, frequently called just bitwise ORing, is used to set some specified bits of a word to 1. For
example, the statement
w1 = w1 | 07;
sets the three rightmost bits of w1 to 1, regardless of the state of these bits before the
operation was performed. Of course, you could have used a special assignment operator
in the statement, as follows:
w1 |= 07;
If w1 and w2 were set equal to octal 0536 and octal 0266, respectively, then the result of
w1 Exclusive-ORed with w2 would be octal 0750, as illustrated:
The ones complement operator (~) should not be confused with the arithmetic minus
operator (–) or with the logical negation operator (!). So if w1 is defined as an int, and
set equal to 0, then –w1 still results in 0. If you apply the ones complement operator to
w1, you end up with w1 being set to all ones, which is –1 when treated as a signed value
in twos complement notation. Finally, applying the logical negation operator to w1 produces the result true (1) because w1
is false (0).
The ones complement operator is useful when you don’t know the precise bit size of
the quantity that you are dealing with in an operation. Its use can help make a program
more portable—in other words, less dependent on the particular computer on which the
program is running and, therefore, easier to get running on a different machine. For
example, to set the low-order bit of an int called w1 to 0, you can AND w1 with an int
consisting of all 1s except for a single 0 in the rightmost bit. So a statement in C such as
w1 &= 0xFFFFFFFE;
works fine on machines in which an integer is represented by 32 bits.
If you replace the preceding statement with
w1 &= ~1;
w1 gets ANDed with the correct value on any machine because the ones complement of
1 is calculated and consists of as many leftmost one bits as are necessary to fill the size of
an int (31 leftmost bits on a 32-bit integer system).
Program summarizes the various bitwise operators presented thus far. Before
proceeding, however, it is important to mention the precedences of the various operators. The AND, OR, and Exclusive-
OR operators each have lower precedence than any
of the arithmetic or relational operators, but higher precedence than the logical AND
and logical OR operators. The bitwise AND is higher in precedence than the bitwise
Exclusive-OR, which in turn is higher in precedence than the bitwise OR. The unary
ones complement operator has higher precedence than any binary operator.
You should work out each of the operations from Program 12.2 with a paper and pencil
to verify that you understand how the results were obtained.The program was run on a
computer that uses 32 bits to represent an int.
In the fourth printf call, it is important to remember that the bitwise AND operator
has higher precedence than the bitwise OR, because this fact influences the resulting
value of the expression.
The fifth printf call illustrates DeMorgan’s rule, namely that ~(~a & ~b) is equal to
a | b and that ~(~a | ~b) is equal to a & b.
Summary
Structure is composition of the different variables of different data types , grouped under same name.
Name given to structure is called as tag.
Structure member may be of different data type including user defined data-type also.
When we declare a structure, memory is not allocated for un-initialized variable.
One structure can be declared inside other structure as we declare structure members inside a structure. This
is known as nested structure.
Structure can be passed to function as a Parameter.
Structures can be created and accessed using pointers.
Union, like structures, contain members whose individual data types may differ from one another. 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.
C provides a capability that enables you to assign an alternate name to a data type.This is done with a
statement known as typedef..
An enumerated data type definition is initiated by the keyword enum. Immediately following this keyword is
the name of the enumerated data type, followed by a list of identifiers (enclosed in a set of curly braces) that
define the permissible values that can be assigned to the type.
Bit operations can be performed on any type of integer value in C—be it short, long, long long, and signed or
unsigned—and on characters, but cannot be performed on floating-point values.
Questions for Exercises
1. What is Structure? Explain in detail.
2. Explain the advantages of structure type over the array the variable.
The C programming Language, By Brian W. Kernighan and Dennis M. Ritchie, Prentice-Hall , 2004
Programming in C, By Stephen G. Kochan, Fourth Edition, 2001
Let Us C, By Yashavant P. Kanetkar, Fifth Edition, 2012
Programming with C, Second Edition, Byron Gottfried, Tata McGraw Hill, 2003.
C. The Complete Reference, Fourth Edition, Herbert Schildt, Tata McGraw Hill, 2002.
The C Primer, Leslie Hancock, Morris Krieger, Mc Gravy Hill, 2013.