Unit Iv
Unit Iv
User Defined Data Types - Structure - Nested structures – Pointer and Structures – Array
of structures – Self-referential structures – Dynamic memory allocation - Singly linked list –
typedef – Union - Storage classes and Visibility.
Aspect Structures
A structure is a collection of variables of different data types grouped
Definition
together under a single name.
Each member of the structure has its own memory location, and the size
Memory Usage
of the structure is the sum of the sizes of its members.
Usage Used when you want to store related pieces of information together.
Example Program:
#include <stdio.h>
// Define a structure
struct Student {
int roll_no;
char name[20];
float marks;
};
int main() {
// Declare structure variable
struct Student s1;
// Assign values to members
s1.roll_no = 101;
strcpy(s1.name, "John");
s1.marks = 85.5;
// Display details
printf("Roll Number: %d\n", s1.roll_no);
1
printf("Name: %s\n", s1.name);
printf("Marks: %.2f\n", s1.marks);
return 0;
}
Output:
Roll Number: 101
Name: John
Marks: 85.50
Unions in C
Aspect Unions
A union is a special data type available in C that allows storing different
Definition
data types in the same memory location.
All members share the same memory location, and the size of the union is
Memory Usage
the size of its largest member.
Usage Used when you need to store only one of its members at a time.
Example Program:
#include <stdio.h>
// Define a union
union Number {
int num;
float decimal;
};
int main() {
// Declare union variable
union Number n;
// Assign value to members
n.num = 10;
printf("Integer value: %d\n", n.num);
n.decimal = 3.14;
printf("Float value: %.2f\n", n.decimal);
2
// Since both members share the same memory location, the value of 'num' will be overwritten
printf("Updated Integer value: %d\n", n.num);
return 0;
}
Output:
Integer value: 10
Float value: 3.14
Updated Integer value: 1092616192
3
different types into a single type. The “struct” keyword is used to define a structure. The
size of the structure is equal to or greater than the total size of all of its members.
Example:
#include <stdio.h>
// Define a structure for representing a point in 2D space
struct Point {
int x;
int y;
};
int main() {
// Declare a structure variable
struct Point p1;
// Initialize structure members
p1.x = 10;
p1.y = 20;
// Access and display structure members
printf("Coordinates of p1: (%d, %d)\n", p1.x, p1.y);
return 0;
}
Output:
Coordinates of p1: (10, 20)
2. Union
Unions are similar to structures in many ways. What makes a union different is that all
the members in the union are stored in the same memory location resulting in only one
member containing data at the same time. The size of the union is the size of its largest
member. Union is declared using the “union” keyword.
Example:
#include <stdio.h>
// Define a union for storing different types of data
union Data {
int i;
float f;
char c;
};
int main() {
4
// Declare a union variable
union Data data;
// Assign values to different members of the union
data.i = 10;
printf("Integer value: %d\n", data.i);
data.f = 3.14;
printf("Float value: %.2f\n", data.f);
data.c = 'A';
printf("Character value: %c\n", data.c);
return 0;
}
Output:
Character value: A
3. Enumeration
Enum is short for “Enumeration”. It allows the user to create custom data types with a set
of named integer constants. The “enum” keyword is used to declare an enumeration.
Enum simplifies and makes the program more readable.
Example:
#include <stdio.h>
// Define an enumeration for days of the week
enum Weekday {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
};
int main() {
// Declare a variable of type enum Weekday
enum Weekday today;
// Assign a value to the variable
today = Wednesday;
// Display the value of the variable
5
printf("Today is %d\n", today + 1);
return 0;
}
Output:
Today is 3
4. typedef
typedef is used to redefine the existing data type names. Basically, it is used to provide
new names to the existing data types. The “typedef” keyword is used for this purpose;
Example:
#include <stdio.h>
// Define a typedef for the data type "struct student"
typedef struct {
int roll_no;
char name[50];
float marks;
} Student;
int main() {
// Declare a variable of type Student using the typedef
Student s1;
// Assign values to the members of the structure
s1.roll_no = 101;
strcpy(s1.name, "John");
s1.marks = 85.5;
// Display the details of the student
printf("Student Details:\n");
printf("Roll Number: %d\n", s1.roll_no);
printf("Name: %s\n", s1.name);
printf("Marks: %.2f\n", s1.marks);
return 0;
}
Output:
Student Details:
Roll Number: 101
Name: John
Marks: 85.50
6
NESTED STRUCTURES
A nested structure in C is a structure within structure. One structure can be declared
inside another structure in the same way structure members are declared inside a structure.
Example:
#include <stdio.h>
// Outer structure definition
struct OuterStruct {
// Inner structure definition inside the outer structure
struct InnerStruct {
// Members of the inner structure
int inner_member1;
char inner_member2;
} inner; // Declaration of inner structure variable
7
Output:
Inner Member 1: 10
Inner Member 2: A
Outer Member 1: 20
Outer Member 2: 3.14
POINTER AND STRUCTURES
A structure pointer is defined as the pointer which points to the address of the memory block that
stores a structure known as the structure pointer. Complex data structures like Linked lists, trees,
graphs, etc. are created with the help of structure pointers. The structure pointer tells the address
of a structure in memory by pointing the variable to the structure variable.
Example:
// C program to demonstrate structure pointer
#include <stdio.h>
struct point {
int value;
};
int main()
{
struct point s;
// Initialization of the structure pointer
struct point* ptr = &s;
return 0;
}
Accessing the Structure Member with the Help of Pointers
There are two ways to access the members of the structure with the help of a structure pointer:
1. With the help of (*) asterisk or indirection operator and (.) dot operator.
2. With the help of ( -> ) Arrow operator.
struct Student {
int roll_no;
8
char name[30];
char branch[40];
int batch;
};
int main()
{
s1.roll_no = 27;
strcpy(s1.name, "Kamlesh Joshi");
strcpy(s1.branch, "Computer Science And Engineering");
s1.batch = 2019;
return 0;
}
Output:
1
9
char branch[40];
int batch;
};
return 0;
}
Output:
Enter the Roll Number of Student
27
Enter Name of Student
Kamlesh_Joshi
Enter Branch of Student
10
Computer_Science_And_Engineering
Enter batch of Student
2019
Student details are:
Roll No: 27
Name: Kamlesh_Joshi
Branch: Computer_Science_And_Engineering
Batch: 2019
ARRAY OF STRUCTURES
An array of structures combines both an array and a structure to handle complex data
neatly. Instead of creating many separate variables of structure, we use an array of structures.
Each element in this array is a structure on its own and since the array elements are stored
continuously in memory, it allows for quick access and makes our program more efficient and
straightforward.
Example:
#include <stdio.h>
struct candidate {
int roll_no;
char grade;
float marks[4];
};
printf("Marks secured:\n");
int i;
11
for (i = 0; i < len; i++) {
int main()
display(A);
return 0;
Output:
Roll number : 1
Grade : A
Marks secured:
Subject 1 : 98.50
Subject 2 : 77.00
Subject 3 : 89.00
Subject 4 : 78.50
SELF-REFERENTIAL STRUCTURES
Self-referential structure in C++ are those structure that contains one or more than one
pointer as their member which will be pointing to the structure of the same type. In simple
words, a structure that points to the structure of the same type is known as a self-referential
structure.
Self-referential structures are mainly used for the implementation of dynamic data
structures like tree, linked list, etc.Structures are non-primitive data type which is used to hold
different pre-defined or primitive data types like int, float, double, etc. Structures in C++ are
initialized by using the struct keyword followed by the name of the structure. The structure
reduces the overall complexity of the C++ program.
12
Note: The self-referential structure can contain only pointers of the same type, other
variables of the same type are not allowed.
In C++, the struct keyword is not mandatory before the declaration of a variable. In C, it
is mandatory to use the struct keyword.
Declaration
struct node
{
int data;
node* next;
};
In the above declaration, *next is the pointer of the node type pointing to the same type
of structure.
Example:
#include <iostream>
using namespace std;
struct node
{
int data;
node* next;
};
int main()
{
node obj;
obj.data=60;
obj.next=NULL;
13
return 0;
}
Types of Self-Referential Structures
There are two types of self-referential structure which are as follows:
1. Self Referential Structure with Single Link
2. Self-Referential Structure with Multiple Links
Self-Referential Structure with Single Link
A structure is said to be a self-referential structure with a single link if it contains only
one pointer link as a member, pointing to the same structure. This structure contains only one
link.
Example:
#include <iostream>
using namespace std;
struct node
{
int data;
node *next;
};
int main()
{
node obj1; // Declaring the object of the node
// Initializing the values of members using obj1
obj1.next = NULL;
obj1.data = 10;
node obj2; // Declaring one more object
// Initializing the values of members using obj1
obj2.next = NULL;
obj2.data = 20;
// Address of obj2 is stored in the next pointer of obj1
obj1.next = &obj2;
14
// Accessing the members of obj2 using next pointer of obj1
cout << obj1.next->data;
return 0;
}
Output:
20
Example:
#include <iostream>
using namespace std;
struct node
{
int data;
node *prev;
node *next;
};
int main()
{
node obj1; // Declaring the object of the node
15
node obj2; // Declaring another object
// Linking Forward
obj1.next = &obj2;
obj2.next = &obj3;
// Linking Backward
obj2.prev = &obj1;
obj3.prev = &obj2;
16
cout << obj3.prev->data << " ";
cout << obj3.data;
return 0;
}
Output:
Accessing data by obj1
10 20 30
Accessing data by obj2
10 20 30
Accessing data by obj3
10 20 20
DYNAMIC MEMORY ALLOCATION
Since C is a structured language, it has some fixed rules for programming. One of them
includes changing the size of an array. An array is a collection of items stored at contiguous
memory locations.
As can be seen, the length (size) of the array above is 9. But what if there is a requirement
to change this length (size)? For example,
If there is a situation where only 5 elements are needed to be entered in this array. In this
case, the remaining 4 indices are just wasting memory in this array. So there is a
requirement to lessen the length (size) of the array from 9 to 5.
Take another situation. In this, there is an array of 9 elements with all 9 indices filled. But
there is a need to enter 3 more elements in this array. In this case, 3 indices more are
required. So the length (size) of the array needs to be changed from 9 to 12.
1. malloc()
2. calloc()
3. free()
4. realloc()
17
malloc() method
The “malloc” or “memory allocation” method in C is used to dynamically allocate a
single large block of memory with the specified size. It returns a pointer of type void which
can be cast into a pointer of any form. It doesn’t Initialize memory at execution time so that it
has initialized each block with the default garbage value initially.
Syntax of malloc() in C
ptr = (cast-type*) malloc(byte-size)
For Example:
ptr = (int*) malloc(100 * sizeof(int));
Since the size of int is 4 bytes, this statement will allocate 400 bytes of memory. And, the
pointer ptr holds the address of the first byte in the allocated memory.
Example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
// This pointer will hold the
// base address of the block created
int* ptr;
int n, i;
// Get the number of elements for the array
printf("Enter number of elements:");
scanf("%d",&n);
printf("Entered number of elements: %d\n", n);
18
// Dynamically allocate memory using malloc()
ptr = (int*)malloc(n * sizeof(int));
// Check if the memory has been successfully
// allocated by malloc or not
if (ptr == NULL)
{
printf("Memory not allocated.\n");
exit(0);
}
else
{
// Memory has been successfully allocated
printf("Memory successfully allocated using malloc.\n");
// Get the elements of the array
for (i = 0; i < n; ++i)
{
ptr[i] = i + 1;
}
// Print the elements of the array
printf("The elements of the array are: ");
for (i = 0; i < n; ++i)
{
printf("%d, ", ptr[i]);
}
}
return 0;
}
Output:
Enter number of elements: 5
19
calloc() method
1. “calloc” or “contiguous allocation” method in C is used to dynamically allocate the
specified number of blocks of memory of the specified type. it is very much similar to
malloc() but has two different points and these are:
2. It initializes each block with a default value ‘0’.
3. It has two parameters or arguments as compare to malloc().
Syntax of calloc() in C
ptr = (cast-type*)calloc(n, element-size);
here, n is the no. of elements and element-size is the size of each element.
For Example:
ptr = (float*) calloc(25, sizeof(float));
This statement allocates contiguous space in memory for 25 elements each with the size of the
float.
Example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
// This pointer will hold the
// base address of the block created
int* ptr;
int n, i;
// Get the number of elements for the array
n = 5;
printf("Enter number of elements: %d\n", n);
20
// Dynamically allocate memory using calloc()
ptr = (int*)calloc(n, sizeof(int));
// Check if the memory has been successfully
// allocated by calloc or not
if (ptr == NULL)
{
printf("Memory not allocated.\n");
exit(0);
}
else
{
// Memory has been successfully allocated
printf("Memory successfully allocated using calloc.\n");
// Get the elements of the array
for (i = 0; i < n; ++i)
{
ptr[i] = i + 1;
}
// Print the elements of the array
printf("The elements of the array are: ");
for (i = 0; i < n; ++i)
{
printf("%d, ", ptr[i]);
}
}
return 0;
}
Output:
Enter number of elements: 5
21
free() method
“free” method in C is used to dynamically de-allocate the memory. The memory
allocated using functions malloc() and calloc() is not de-allocated on their own. Hence the
free() method is used, whenever the dynamic memory allocation takes place. It helps to reduce
wastage of memory by freeing it.
Syntax of free() in C
free(ptr);
Example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
// This pointer will hold the
// base address of the block created
int *ptr, *ptr1;
int n, i;
// Get the number of elements for the array
n = 5;
printf("Enter number of elements: %d\n", n);
// Dynamically allocate memory using malloc()
ptr = (int*)malloc(n * sizeof(int));
// Dynamically allocate memory using calloc()
ptr1 = (int*)calloc(n, sizeof(int));
22
// Check if the memory has been successfully
// allocated by malloc or not
if (ptr == NULL || ptr1 == NULL)
{
printf("Memory not allocated.\n");
exit(0);
}
else
{
// Memory has been successfully allocated
printf("Memory successfully allocated using malloc.\n");
// Free the memory
free(ptr);
printf("Malloc Memory successfully freed.\n");
// Memory has been successfully allocated
printf("\nMemory successfully allocated using calloc.\n");
// Free the memory
free(ptr1);
printf("Calloc Memory successfully freed.\n");
}
return 0;
}
Output:
Enter number of elements: 5
Memory successfully allocated using malloc.
Malloc Memory successfully freed.
realloc() method
“realloc” or “re-allocation” method in C is used to dynamically change the memory
allocation of a previously allocated memory. In other words, if the memory previously
allocated with the help of malloc or calloc is insufficient, realloc can be used to dynamically
23
re-allocate memory. re-allocation of memory maintains the already present value and new
blocks will be initialized with the default garbage value.
Syntax of realloc() in C
ptr=realloc(ptr,newSize);
where ptr is reallocated with new size 'newSize'.
#include <stdio.h>
#include <stdlib.h>
int main()
{
// This pointer will hold the
// base address of the block created
int* ptr;
int n, i;
// Get the number of elements for the array
n = 5;
printf("Enter number of elements: %d\n", n);
// Dynamically allocate memory using calloc()
ptr = (int*)calloc(n, sizeof(int));
// Check if the memory has been successfully
// allocated by malloc or not
if (ptr == NULL)
{
printf("Memory not allocated.\n");
24
exit(0);
}
else
{
// Memory has been successfully allocated
printf("Memory successfully allocated using calloc.\n");
// Get the elements of the array
for (i = 0; i < n; ++i) {
ptr[i] = i + 1;
}
// Print the elements of the array
printf("The elements of the array are: ");
for (i = 0; i < n; ++i)
{
printf("%d, ", ptr[i]);
}
// Get the new size for the array
n = 10;
printf("\n\nEnter the new size of the array: %d\n", n);
// Dynamically re-allocate memory using realloc()
ptr = (int*)realloc(ptr, n * sizeof(int));
// Memory has been successfully allocated
printf("Memory successfully re-allocated using realloc.\n");
// Get the new elements of the array
for (i = 5; i < n; ++i)
{
ptr[i] = i + 1;
}
// Print the elements of the array
printf("The elements of the array are: ");
for (i = 0; i < n; ++i)
{
printf("%d, ", ptr[i]);
}
25
free(ptr);
}
return 0;
}
Output:
Enter number of elements: 5
Memory successfully allocated using calloc.
The elements of the array are: 1, 2, 3, 4, 5,
Insertion of a node
To define the insertion of a node in a single linked list in C, you typically need to create a
function that inserts a new node at a specified position in the list.
26
newNode - >
next = *head;
Deletion of a node
To define the deletion of a node in a single linked list in C, you typically need a function
that removes a node from the list, given its value or position.
free (temp);
}
27
// as linked list will end when Node is Null
while(node!=NULL){
printf("%d ",node->data);
node = node->next;
}
printf("\n");
}
TYPEDEF
The typedef is a keyword that is used to provide existing data types with a new name.
The C typedef keyword is used to redefine the name of already existing data types.
When names of datatypes become difficult to use in programs, typedef is used with user-
defined datatypes, which behave similarly to defining an alias for commands.
C typedef Syntax
typedef existing_name alias_name;
Use of typedef in C
Following are some common uses of the typedef in C programming:
The typedef keyword gives a meaningful name to the existing data type which helps other
users to understand the program more easily.
It can be used with structures to increase code readability and we don’t have to type struct
repeatedly.
The typedef keyword can also be used with pointers to declare multiple pointers in a single
statement.
It can be used with arrays to declare any number of variables.
1. typedef struct
typedef can also be used with structures in the C programming language. A new data
type can be created and used to define the structure variable.
Example:
// C program to implement
// typedef with structures
28
#include <stdio.h>
#include <string.h>
// using typedef to define an alias for structure
typedef struct students
{
char name[50];
char branch[50];
int ID_no;
} stu;
// Driver code
int main()
{
stu st;
strcpy(st.name, "Kamlesh Joshi");
strcpy(st.branch, "Computer Science And Engineering");
st.ID_no = 108;
ID_no: 108
29
Syntax:
typedef int* Int_ptr;
Example:
// C program to implement
// typedef with pointers
#include <stdio.h>
typedef int* ptr;
// Driver code
int main()
{
ptr var;
*var = 20;
Syntax:
typedef int arr[20]
Example:
// C program to implement typedef with array
#include <stdio.h>
typedef int Arr[4];
30
// Driver code
int main()
{
Arr temp = { 10, 20, 30, 40 };
printf("typedef using an array\n");
10 20 30 40
UNION
A union is a special data type available in C that allows to store different data types in
the same memory location. You can define a union with many members, but only one member
can contain a value at any given time. Unions provide an efficient way of using the same
memory location for multiple purpose.
All the members of a union share the same memory location. Therefore, if we need to use
the same memory location for two or more members, then union is the best data type for that.
The largest union member defines the size of the union.
Union variables are created in same manner as structure variables. The keyword union is
used to define unions in C language.
Syntax:
union [union tag]
{
member definition;
member definition;
...
member definition;
} [one or more union variables];
31
Example:
#include <stdio.h>
#include <string.h>
union Data
{
int i;
float f;
char str[20];
};
intmain()
{
union Data data;
printf("Memory occupied by Union Data: %d \n", sizeof(data));
return 0;
}
Output:
Memory occupied by Union Data: 20
Output:
Note: This stucture will occupy 28 bytes (4 + 4 + 20).
Memory occupied by Struct Data: 28
Syntax
To specify the storage class for a variable, the following syntax is to be followed:
storage_class var_data_type var_name;
32
1. auto
This is the default storage class for all the variables declared inside a function or a block.
Hence, the keyword auto is rarely used while writing programs in C language. Auto variables
can be only accessed within the block/function they have been declared and not outside them
(which defines their scope). Of course, these can be accessed within nested blocks within the
parent block/function in which the auto variable was declared.
However, they can be accessed outside their scope as well using the concept of pointers
given here by pointing to the very exact memory location where the variables reside. They are
assigned a garbage value by default whenever they are declared.
Example:
#include <stdio.h>
void function()
{
auto int a = 10; // auto storage class is implicit here
printf("Value of 'a' inside function: %d\n", a);
}
int main()
{
function();
// 'a' is not accessible here since it's local to the function
// printf("Value of 'a' outside function: %d\n", a); // This will result in an error
return 0;
}
33
Output:
Value of 'a' inside function: 10
2. extern
Extern storage class simply tells us that the variable is defined elsewhere and not within
the same block where it is used. Basically, the value is assigned to it in a different block and this
can be overwritten/changed in a different block as well. So an extern variable is nothing but a
global variable initialized with a legal value where it is declared in order to be used elsewhere. It
can be accessed within any function/block.
Also, a normal global variable can be made extern as well by placing the ‘extern’
keyword before its declaration/definition in any function/block. This basically signifies that we
are not initializing a new variable but instead, we are using/accessing the global variable only.
The main purpose of using extern variables is that they can be accessed between two different
files which are part of a large program.
Example:
#include <stdio.h>
int count; // Declaration of count variable with extern storage class
void incrementCount()
{
extern int count; // Declaration is optional here
count++;
}
int main()
{
incrementCount();
printf("Value of 'count': %d\n", count); // Prints the updated value of count
return 0;
}
Output:
Value of 'count': 1
3. static
This storage class is used to declare static variables which are popularly used while
writing programs in C language. Static variables have the property of preserving their value even
after they are out of their scope! Hence, static variables preserve the value of their last use in
their scope. So we can say that they are initialized only once and exist till the termination of the
program. Thus, no new memory is allocated because they are not re-declared.
34
Their scope is local to the function to which they were defined. Global static variables
can be accessed anywhere in the program. By default, they are assigned the value 0 by the
compiler.
Example:
#include <stdio.h>
void function()
{
static int count = 0;
count++;
printf("Function called %d times.\n", count);
}
int main() {
function(); // Prints "Function called 1 times."
function(); // Prints "Function called 2 times."
function(); // Prints "Function called 3 times."
return 0;
}
Output:
Function called 1 times.
Function called 2 times.
Function called 3 times.
4. register
This storage class declares register variables that have the same functionality as that of
the auto variables. The only difference is that the compiler tries to store these variables in the
register of the microprocessor if a free register is available. This makes the use of register
variables to be much faster than that of the variables stored in the memory during the runtime of
the program.
If a free registration is not available, these are then stored in the memory only. Usually, a
few variables which are to be accessed very frequently in a program are declared with the
register keyword which improves the running time of the program. An important and interesting
point to be noted here is that we cannot obtain the address of a register variable using pointers.
Example:
#include <stdio.h>
int main()
{
35
register int x = 5;
printf("Value of 'x' stored in register: %d\n", x);
return 0;
}
Output:
Value of 'x' stored in register: 5
36