Module 6
Module 6
Module 6
By Asst. Prof. Sudeshna Baliarsingh
Information & Technology Dept.
KJSIT, Mumbai
Pointers and Files
● Fundamentals of pointers
● Declaration, initialization and dereferencing of
● pointers
● Operations on Pointers
● Concept of dynamic memory allocation
● Types of File, File operation- Opening, Closing,
● Creating, Reading, Processing File
Fundamentals of pointers
Pointers are the variables or the special variables which contain address
Syntax of C Pointers
The syntax of pointers is similar to the variable declaration in C, but we use the
( * ) dereferencing operator in the pointer declaration.
datatype * ptr;
where
int n = 50;
In our computer’s memory, there are now 4 bytes somewhere that have the binary value
of 50, with some value for its address, like 0x123:
What is 0x123?
Output:
We got dcbc14ac as the
Value of the variable n is: 50
address of variable n.
Memory address of the variable n
is: dcbc14ac
What's the role of a pointer in all this?
A pointer is a variable that stores an address in memory, where some other variable might be stored.
Syntax of Pointers in C
data_type * pointer_variable_name;
Some of the valid pointers declarations in C are as follows:
Allocated to ” a “
I can write for simplicity purpose
int a=10;
In pointer declaration, we only declare the pointer but do not initialize it. To
declare a pointer, we use the ( * ) dereference operator before its name.
Example
int *ptr;
The pointer declared here will point to some random memory address as
it is not initialized. Such pointers are called wild pointers.
2. Pointer Initialization
Pointer initialization is the process where we assign some initial value to the pointer variable. We
generally use the ( & ) addressof operator to get the memory address of a variable and then store
it in the pointer variable.
Example
We can also declare and initialize the pointer in a single step. This method is called pointer
definition as the pointer is declared and initialized at the same time.
Example:
Int a=10;
Int *p=&a;
Or
Int a=10,*p=&a;
Int *p=&a, a=10 // here we are declaring a after addressing a so this is illegal
3. Accessing the pointer by Pointer Dereferencing
Dereferencing a pointer is the process of accessing the value stored in the memory address specified in
the pointer. We use the same ( * ) dereferencing operator or indirection operator that we used in the pointer
declaration.
float x,y;
Int a,*ptr;
ptr=&a;
ptr=&a;
Note that the '*' operator that we used to declare a variable as pointer is also used
to get the value at that address that the pointer holds. This is also known as
dereferrencing.
Output
10
Types of Pointers in C
Null Pointer in C
If we don't initialize a pointer after declaration then by default the pointer is a Null pointer . We can also explicitly
do this by assigning the NULL value at the time of pointer declaration. This method is useful when you do not
assign any address to the pointer.
Output
0
Void Pointer in C
The void pointer is a generic pointer that does not have any data type assosiated with it. The datatype of void
pointer can be of any type and can be typecast to any type.
Output
8
Wild Pointer in C
Wild pointers are basically uninitialized pointers that points to arbitrary memory location and may cause a program
to crash or behave badly.
Dangling Pointer in C
A dangling pointer is a pointer that is pointing to a memory location that has been deleted or released. Let's
understand with an example---
When we create a pointer "ptr"
it gets some memory in stack
of the same size as its data
type. Then we called malloc
function to create a memory in
heap and assign the address
of that memory to the pointer
variable. Now the magic
happens, when we call "free"
on "ptr" the memory address of
the heap got deleted and now
"ptr" is pointing to a location
that has been deleted. This is
called dangling pointer. Now
when we aasign "NULL" to
"ptr" it no more remains a
dangling pointer & becomes a
NULL pointer.
Pointer Operations
Pointer Arithmetic is the set of valid arithmetic operations that can be performed
on pointers. The pointer variables store the memory address of another
variable. It doesn’t store any value.
Hence, there are only a few operations that are allowed to perform on Pointers
in C language. The C pointer arithmetic operations are slightly different from the
ones that we generally use for mathematical calculations. These operations are:
Increment/Decrement of a Pointer
Addition of integer to a pointer
Subtraction of integer to a pointer
1. Increment/Decrement of a Pointer
Increment: It is a condition that also comes under addition. When a pointer is incremented, it
actually increments by the number equal to the size of the data type for which it is a pointer.
For Example:
If an integer pointer that stores address 1000 is incremented, then it will increment by 4(size of
an int), and the new address will point to 1004. While if a float type pointer is incremented
then it will increment by 4(size of a float) and the new address will be 1004.
Decrement: It is a condition that also comes under subtraction. When a pointer is decremented,
it actually decrements by the number equal to the size of the data type for which it is a pointer.
For Example:
If an integer pointer that stores address 1000 is decremented, then it will decrement by 4(size
of an int), and the new address will point to 996. While if a float type pointer is decremented
then it will decrement by 4(size of a float) and the new address will be 996.
Note: It is assumed here that the architecture is 64-bit and all the data types are sized accordingly. For example,
integer is of 4 bytes.
Explanation :
In the example without using array, ptr initially points to the address of variable
a. Then, it's incremented (ptr++) to move to the next memory location (which is not
guaranteed to be valid). After that, it's decremented (ptr--) back to the previous
memory location, which points back to the variable a. Finally, it's dereferenced
(*ptr) to get the value it's pointing to.
In the example with using array, ptr initially points to the first element of the array
arr. Then, it's incremented (ptr++) to point to the next element, and decremented
(ptr--) back to the previous element. Each time, it's dereferenced (*ptr) to get the
value it's pointing to.
Addition of Integer to Pointer
When a pointer is added with an integer value, the value is first multiplied by the size of the data type and then
added to the pointer.
For Example:
Consider the same example as above where the ptr is an integer pointer that stores 1000 as an address. If we
add integer 5 to it using the expression, ptr = ptr + 5, then, the final address stored in the ptr will be ptr =
1000 + sizeof(int) * 5 = 1020.
Output
1 2 3 4 5
Concept of dynamic
memory allocation
Concept of dynamic memory allocation
In programming, particularly in C, managing memory efficiently is crucial. This
begins with understanding the distinction between Static and Dynamic Memory
Allocation.
Static Memory Allocation, occurring at compile-time, assigns a fixed
memory space to variables or arrays. However, this predefined space can
sometimes be insufficient.
There are further four components in which our system's memory is divided:
1. Stack Segment (Static Memory)
2. Global Variables Segment (Static Memory)
3. Instructions / Text Segment (Static Memory)
4. Heap Segment (Dynamic Memory)
The amount of memory
allocated for Stack,
Global Variables, and
Instructions / Text
during compile-time is
invariable and cannot
be reused until the
program execution
finishes. However, the
Heap segment of the
memory can be used at
run-time and can be
expanded until the
system's memory
exhausts.
some important points related to all the memory segments :
Instructions / Text
Global variable also known as static variables and can be declared by two methods,
Using static keyword, ex. static int i = 0;
Declaring variable outside main() or any other function.
These variables are stored in the Static Memory during the compile-time of our program.
Stack
Stack is a constant space (memory) allocated by our operating system to store local variables,
function calls and local statements that are present in the function definition. It is the major part of
the Static Memory in our system.
There are some drawbacks of stack space as follows:
The memory allocated for stack can't grow during the run-time of an application.
We can't allocate or deallocate memory during execution.
Heap
Heap is the Dynamic Memory of our program, It can be also be imagined as a big free pool
of memory available to us.
The space occupied by heap section is not fixed, it can vary during the run-time of our
program and there are functions to perform allocation and deallocation of memory
blocks during run-time.
Heap space can grow as long as we do not run out of the system's memory itself, however it
is not in the best interest of a programmer to exhaust the system's memory, so we need to be
really careful while using the heap space in our program.
Note : A machine's memory is one of the most useful resource available to us that can be
used as both Statically and Dynamically. So, we have to make sure to manage it well and not
waste it during the execution of our program.
Memory Allocation Process
Let us now see how our Operating System processes the allocation of memory through
an example.
We will see how the memory is allocated at compile-time in this section using the
example of calculating Greatest Common Divisor (GCD) and Least Common Multiple
(LCM).
Enter two values to find their
Greatest Common Divisor and
Least Common Multiple : 12 15
Greatest Common Divisor : 3
Least Common Multiple : 60
Sum of GCD and LCM : 63
Explanation of Memory Allocation Process for the above GCD and LCM example :
Explanation :
The first rectangular box represents the memory reserved for text / instructions,
second box as memory reserved for global variables section, third box as the space
reserved for stack and fourth box represents the heap space.
When we run our program, first the main() function is called, then some amount of
memory from the stack frame is allocated for the execution of main() function and as
sum is a global variable, it has been given a space in the global segment.
Heap space remains empty throughout the execution of the program as there is no
allocation of memory during run-time.
The amount of memory allocated for a function in the stack can be called as a stack
frame. All of the local variables, arguments and the information in a function is stored
within the stack frame allocated to that function and as soon as a function returns
something or reaches its last statement, it is cleared from the stack memory.
When the main() finishes, program also finishes. In the end, space occupied by our
global variables also gets cleared.
Introduction to Dynamic Memory Allocation in C
Dynamic Memory Allocation in C is a process in which we allocate or deallocate a block of memory
during the run-time of a program.
There are four functions malloc(), calloc(), realloc() and free() present in <stdlib.h> header file
that are used for Dynamic Memory Allocation in our system.
It can also be referred to as a procedure to use Heap Memory in which we can vary the size of
a variable or Data Structure (such as an Array) during the lifetime of a program using the
library functions.
Dynamic Memory Allocation is considered as a very important concept in the field of Data
Structures and is used in almost every Data Structures like Linked Lists, Stacks, Dynamic Arrays,
Queue, etc.
Now, Let us see the definition, syntax and some examples of each library functions below.
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.
They are:
1. malloc()
2. calloc()
3. free()
4. realloc(
C 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:
In the main() function, first we have declared and initialized a char pointer
ptr with a dynamic memory block allocated using malloc() function.
Now, if the system memory is exhausted it will print Memory Error! (ptr =
NULL) in the output console, else we have assigned character S in the
memory block pointed by ptr and printf("%c", *ptr); prints S in the output.
return 0; exits the program successfully.
C calloc() Method
calloc() is a method in C which is also used to allocate memory blocks in
the heap section, but it is generally used to allocate a sequence of
memory blocks (contiguous memory) like an array of elements. It is
also present in <stdlib.h> header file.
General Syntax:
(cast-data-type *)calloc(num, size-in-bytes);
calloc() function takes two arguments, first is the size of the array
(number of elements) and second is the sizeof() data type (in bytes) of
which we have to make an array.
Variable Declaration:
int n = 5;: This variable n holds the number of elements we want in our
array.
int *array;: This declares a pointer array that we will use to hold the
address of the memory allocated by calloc.
Memory Allocation:
Syntax of free()
General syntax:
free( pointer );
free() takes one argument and it is the pointer containing the address of
the memory block that is to be freed or deallocated.
Example :
free(arr);
In the above statement, we are deallocating memory block(s) pointed by a
pointer arr in the memory.
C realloc() Method
Syntax of realloc()
General syntax :
(cast-data-type *)realloc(ptr, new-size-in-bytes)
realloc() takes two arguments, one is the pointer pointing the the
memory which is to be reallocated and second is the new size in
bytes.
Example : int *arr2 = (int *)realloc(arr, (n / 2) * sizeof(int));
In the above statement, we are reallocating arr pointer's memory to
reduce it to half and assigning it to arr2 pointer, other half of the array
will now contain garbage values.
Note : malloc(n *
sizeof(int)); and calloc(n,
sizeof(int)); both allocates
the same amount of
memory, but malloc()
function does't initialize the
elements in the
memory(garbage values),
while the calloc() function
initializes all the element in
the memory to 0.
Basics of File Handling in C
File handling in C is the process in which we create, open, read, write, and close
operations on a file. C language provides different functions such as fopen(),
fwrite(), fread(), fseek(), fprintf(), etc. to perform input, output, and many different
C file operations in our program.
File handling in C stores data of our program in our local store, which can be used
at any time because as the execution of a program completes, our data is lost.
Therefore, we need to save our data in any file form - text or binary files.
We can perform tasks like opening, reading the existing file, writing or adding new
content, creating a new file, closing the file, or even saving the file to a certain
location using C.
Basics of File Handling in C
When a program is terminated, the entire data is lost. Storing in a file will preserve
your data even if the program terminates.
If you have to enter a large number of data, it will take a lot of time to enter them
all.
However, if you have a file containing all the data, you can easily access the
contents of the file using a few commands in C.
You can easily move your data from one computer to another without any
changes.
Why do we need File Handling in C?
So far the operations using the C program are done on a prompt/terminal which is not stored
anywhere. The output is deleted when the program is closed. But in the software industry,
most programs are written to store the information fetched from the program. The use of file
handling is exactly what the situation calls for.
In order to understand why file handling is important, let us look at a few features of using
files:
Reusability: The data stored in the file can be accessed, updated, and deleted anywhere and
anytime providing high reusability.
Portability: Without losing any data, files can be transferred to another in the computer
system. The risk of flawed coding is minimized with this feature.
Efficient: A large amount of input may be required for some programs. File handling allows
you to easily access a part of a file using few instructions which saves a lot of time and
reduces the chance of errors.
Storage Capacity: Files allow you to store a large amount of data without having to worry
about storing everything simultaneously in a program.
Types of Files in C
A file can be classified into two types based on the way the file stores the data. They are as follows:
Text Files
Binary Files
types of files in c
1. Text Files
A text file contains data in the form of ASCII characters and is generally used to store a stream of characters.
Each line in a text file ends with a new line character (‘\n’).
It can be read or written by any text editor.
They are generally stored with .txt file extension.
Text files can also be used to store the source code.
2. Binary Files
A binary file contains data in binary form (i.e. 0’s and 1’s) instead of ASCII characters. They contain data that is
stored in a similar manner to how it is stored in the main memory.
The binary files can be created only from within a program and their contents can only be read by a program.
More secure as they are not easily readable.
They are generally stored with .bin file extension.
C File Operations
FILE* pointer_name;
Syntax of fopen()
FILE* fopen(const char *file_name, const char *access_mode);
Parameters
file_name: name of the file when present in the same directory as the source file. Otherwise,
full path.
access_mode: Specifies for what operation the file is being opened.
Return Value
If the file is opened successfully, returns a file pointer to it.
If the file is not opened, then returns NULL.
File opening modes in C
File opening modes or access modes specify the allowed operations on the file to be opened.
They are passed as an argument to the fopen() function. Some of the commonly used file
access modes are listed below:
As given above, if you want to perform operations on a binary file, then you have to append ‘b’ at the last.
For example, instead of “w”, you have to use “wb”, instead of “a+” you have to use “a+b”.
Output
The file is not opened. The
program will now exit.
FILE *fptr;
fptr = fopen("filename.txt", "w");
Output
The file is created
Successfully.
Reading From a File
The file read operation in C can be performed using functions fscanf() or fgets(). Both the functions performed the
same operations as that of scanf and gets but with an additional parameter, the file pointer. There are also other
functions we can use to read from a file. Such functions are listed below:
So, it depends on you if you want to read the file line by line or character by character.
Example:
FILE * fptr;
fptr = fopen(“fileName.txt”, “r”);
fscanf(fptr, "%s %s %s %d", str1, str2, str3, &year);
char c = fgetc(fptr);
The getc() and some other file reading functions return EOF (End Of File) when
they reach the end of the file while reading. EOF indicates the end of the file
and its value is implementation-defined.
Note: One thing to note here is that after reading a particular part of the file, the
file pointer will be automatically moved to the end of the last read character.
Write to a File
The file write operations can be performed by the functions fprintf() and fputs() with similarities to read operations. C
programming also provides some other functions that can be used to write data to a file such as:
Example:
FILE *fptr ;
fptr = fopen(“fileName.txt”, “w”);
fprintf(fptr, "%s %s %s %d", "We", "are", "in",
2024);
fputc("a", fptr);
Closing a File
The fclose() function is used to close the file. After successful file
operations, you must always close a file to remove it from the memory.
Syntax of fclose()
fclose(file_pointer);
where the file_pointer is the pointer to the opened file.
Example:
FILE *fptr ;
fptr= fopen(“fileName.txt”, “w”);
---------- Some file Operations -------
fclose(fptr);
In this program, we create a new
file program.bin in the C drive.
char sourceFileName[100], destinationFileName[100], ch;: These lines declare character arrays sourceFileName
and destinationFileName to store the names of the source and destination files respectively. The variable ch is
used to store characters read from the source file.
Now prompt the user to input the names of the source and destination files using printf() and gets() functions.
gets() is used to read the input as it allows reading a string with spaces.
sourceFile = fopen(sourceFileName, "r");: This line opens the source file in read mode ("r") and assigns the file
pointer returned by fopen() to sourceFile.
Then check if the source file was opened successfully. If fopen() returns NULL, it means the file could not be
opened, and an error message is printed. The program then waits for a key press using getch() and returns with
an error code (1).
destinationFile = fopen(destinationFileName, "w");: This line opens the destination file in write mode ("w") and
assigns the file pointer returned by fopen() to destinationFile.
This if block checks if the destination file was opened successfully. If fopen() returns NULL, it means the file could
not be opened, an error message is printed, and the program returns with an error code (1). Also, it closes the
source file before returning.
Then the while loop reads characters from the source file using fgetc() function until the end of file (EOF) is
encountered. Each character read is then written to the destination file using fputc().
Then print a success message indicating that the contents of the source file have been successfully copied to the
destination file.