UNIT IV
Pointer
Def. A pointer is a variable which holds the address of another variable i.e., it points to another variable.
A pointer is a derived data type in C. We can create pointer variables of any data type. Every pointer
stores the address of another variable with same data type only. That means integer pointer is used
store the address of integer variable only and float pointer is used to store the address of float variable
only.
Pointers are variables whose values are memory addresses. Normally, a variable directly contains a
specific value. A pointer, on the other hand, contains an address of a variable that contains a specific
value. A variable name directly references a value, and a pointer indirectly references a value.
Referencing a value through a pointer is called indirection.
A pointer is a variable that points to another variable. This means that a pointer holds the memory
address of another variable.
Accessing the Address of a Variable
Once we declare a variable, then it will be stored in the memory. The address of a variable can be
obtained using the address operator (&).
The & is a unary operator that returns the memory address of its operand. For example, if var is an
integer variable, then &var is its address.
Example:
int i=5;
Suppose if I is stored in memory location 20560, then we can use
printf(“The address of i is: %u”,&i); //Which will print 20560
Note: we have used %u to print the address since memory addresses are unsigned integers.
Declaring Pointers and Initializing
Like variables, pointers in C programming have to be declared before they can be used in program.
Syntax:
<data_type> * <pointer_name>;
Example:
int *i; //pointer to an integer
float *f; //pointer to a float
char *ch; //pointer to a character
double *d; //pointer to a double
After declaring a pointer, we initialize it with a variable address. Pointer initialization is done with the
following syntax:
pointer = &variable;
Example:
int i=5;
int *ptr;
ptr=&i;
Accessing a Variable through its Pointer
We use the symbol “ * ” in front of pointer variable name to access the value of a variable to which
the pointer is pointing.
Syntax: *pointer_variable_name
Example:
int x=5;
int *xptr=&x;
printf(“%d”, x); //prints value of x - 5
printf(“%d”,*xptr); //prints value of x – 5
When a pointer is encountered, the computer knows that it is dealing with an address in memory.
When it sees the asterisk there, it knows to look at the contents of that address, rather than the
address itself. This is called dereferencing a pointer.
Arrays and Pointers
Pointers and Two-Dimensional Arrays
An important application of pointers is using them with arrays. Pointers can be used to access the
elements in an array. The basic advantage of using pointers to array involves convenience and
reduction in memory space for program code, leading to faster execution. Once an array is declared
and initialized, the elements of an array are arranged contiguously in memory. The address of the
first element is needed to access the entire array.
int a[5]={10,20,30,40,50};
10 20 30 40 50
2002 2006 2010 2014 2018
Then,
int *ptr;
this ptr variable is suitable for holding the address of an integer variable. Now, the address of the
start of the array can be assigned to ptr as:
ptr=&a[0];
same as
ptr=a;
The pointer variable ptr now points to first element of the integer array which is an integer value 10.
The name of an array itself gives the base address. Once the pointer gets the base address of an
array, then the successive elements can be accessed very easily by just incrementing a pointer.
ptr++;
when ptr is incremented by 1, then the address of the next element will be stored in ptr (i.e., ptr
contains 2006).
Program: To access the array elements using a pointer.
void main()
{
int a[5]={10,20,30,40,50};
int i;
int *ptr;
ptr=a;
for(i=0;i<5;i++)
{
printf(“address=%u element=%d\n”, ptr, *ptr);
ptr++;
}
}
Output
Address = 2002 Element = 10
Address = 2006 Element = 20
Address = 2010 Element = 30
Address = 2014 Element = 40
Address = 2018 Element = 50
Pointers and Two-Dimensional Arrays
The two-dimensional arrays have two subscripts. The first subscript refers to the row position and
second subscript refers to the column position.
Example:
int A[4][3];
We can initialize this two-dimensional array as:
A[4][3]={{10,20,30},{40,50,60},{70,80,90},{100,110,120}};
10 20 30
40 50 60
70 80 90
100 110 120
A pointer to a single dimensional array contains the address of the first element. In two-dimensional
arrays, the address of the element in the first row and first column of an array is assigned to the
pointer variable.
int *ptr;
ptr=A;
The address of A[0][0] is assigned to ptr. If we do ptr++, the pointer variable points to A[0][1].
Pointer Expressions
Pointer Assignments
We can assign one pointer to another pointer, which is similar of assigning one variable value to an
another variable. When both pointers are same type then we can go for assignment.
Example:
int a=10, b=20;
int *ptr1, *ptr2;
ptr1=&a;
ptr2=&b;
Now, ptr1 is pointing to a and ptr2 is pointing to b.
Pointer Comparison
We can compare two pointers in a relational expression.
Example:
int a[5]={10,20,30,40,50};
int *ptr1, *ptr2;
ptr1=&a[0];
ptr2=&a[3];
10 20 30 40 50
2002 2006 2010 2014 2018
Now ptr1 is pointing to a memory location 2002 and ptr2 is pointing to a memory location 2014.
if(ptr1<ptr2)
printf(“ptr1 points to lower memory than ptr2”);
else
printf(“ptr1 points to higher memory than ptr2”);
Pointer Arithmetic
C language allows arithmetic operations to be performed on pointer variables, to move between the
items in the array. Since pointers are just like any other variables and hence may be used in
expression. It can be incremented, decremented, and a value can be added (or) subtracted to a
pointer in order to modify the contents of the pointer variables. However, a pointer cannot be
multiplied (or) divided by another pointer (or) number. The most common operation on pointers is
incrementing a pointer.
Example:
Let ptr be an integer pointer with current value of 2000.
ptr ------→ pointer name
2000
4028 -----→ ptr’s address
Now, ptr is pointing to memory location 2000. After the expression
ptr++;
ptr contains 2004, not 2001. This is because that each time ptr is incremented, it will point to the
next integer.
ptr ------→ pointer name
2004
4028 -----→ ptr’s address
The ptr’s address will not change by incrementing ptr. Similarly, ptr-- causes to have the value 1996.
Each time a pointer is incremented, it points to the memory location of the next element of its base
type. Each time a pointer is decremented, it points to the location of the previous element.
Arrays of Pointers
A pointer variable always contains an address of another variable, but an array of pointers can
contain address of many variables or addresses of array elements or any other addresses.
Example:
int *ptr[5];
ptr is the array of pointers that can store addresses of 5 integer variables.
Pointers and Functions
Pointers and functions together allow efficient data handling, modifying actual variables, and working
with dynamic memory and arrays.
Passing Arguments to Functions
There are two ways to pass arguments:
(a) Pass by Value
• A copy of the variable is passed.
• Changes inside the function do not affect the original variable.
(b) Pass by Reference (using pointers)
• The address of the variable is passed.
• Allows the function to directly modify the original variable.
Example:
void update(int *p)
{
*p = *p + 5;
}
int main()
{
int x = 10;
update(&x); // x becomes 15 because we passed the address
}
Pointers as Function Parameters
A pointer parameter allows the function to:
• Access the memory location of a variable.
• Read/modify the value stored at that address.
Example:
void change(int *ptr)
{
*ptr = 100;
}
Functions Returning Pointers
A function can return a pointer, but the returned pointer must point to a valid memory location.
Example:
int* getValue()
{
static int x = 50;
return &x;
}
Call By Value Call By Reference
Only value is passed The address is passed
Separate memory locations for formal and actual Only one memory location for both actual and
parameters are created. formal parameters is created.
The changes made to the formal parameters does not Changes made to the formal parameters affects the
affect the value of actual parameters original value of the actual parameters.
Slow. CPU spends time to create memory locations Fast. The manipulation with the address is faster
for formal parameters and to store the values of than the normal variables.
actual parameters in them.
Pointers and Structures
Pointers with structures in C are used to store the memory address of a structure variable, allowing
access to its members using the pointer. Instead of accessing members directly with the dot (.)
operator, a pointer uses the arrow (->) operator to refer to the structure’s data. This approach
makes data access more efficient, supports dynamic memory allocation, and is commonly used in
functions and linked data structures.
Accessing Structure Members Using Pointer
When you have a pointer to a structure, you use the → operator to access its members.
Example:
struct Student
{
int roll;
float marks;
};
struct Student s1 = {101, 89.5};
struct Student *ptr = &s1;
printf("%d", ptr->roll); // same as [Link]
printf("%f", ptr->marks); // same as [Link]
Passing Structures to Functions
Passing a structure by value copies the entire struct: slow for large data.
Passing pointer only sends address: faster and memory efficient.
Example:
void display(struct Student *s)
{
printf("Roll: %d\n", s->roll);
printf("Marks: %.2f\n", s->marks);
}
display(&s1);
Advantages of Pointers
Pointers provide direct access to memory.
Reduces the execution time of the program.
Pointers allows us to perform dynamic memory allocation and deallocation.
Pointers helps us to build complex data structures like linked list, stack, queues, trees, graphs
Pointers allows us to resize the dynamically allocated memory block.
Provides an alternate way to access array elements.
Pointers provide a way to return more than one value to the functions
Pointers are more efficient in handling arrays and data tables
Pointers reduce length and complexity of programs
Using pointer arrays to store character strings, saves data storage space in memory.
Disadvantages of Pointers
Pointers are a little complex to understand.
Pointers can lead to various errors such as segmentation faults or can access a memory
location which is not required at all.
If an incorrect value is provided to a pointer, it may cause memory corruption.
Pointers are also responsible for memory leakage. Dynamically allocated block needs to be
freed explicitly. Otherwise, it would lead to memory leak.
Pointers are slower than normal variables.
Static and Dynamic Memory Allocation
Static memory allocation is the process in which memory for variables is allocated during compile
time. The size of the memory must be known in advance and cannot change during program
execution.
• The compiler decides how much memory is needed before the program runs.
• All memory is fixed during compilation and cannot change during execution.
Where it is stored:
• Stack (local variables)
• Data segment (global variables, static variables)
Characteristics
✔ Memory allocated automatically
✔ Lifetime depends on variable type
✔ No need to manually free memory
✔ Faster compared to dynamic memory
Limitations
✘ Cannot resize memory
✘ Not efficient when size is unpredictable
✘ Large arrays on stack may cause stack overflow
Dynamic memory allocation is the process in which memory is allocated during runtime using
functions like malloc(), calloc(), and realloc(). The programmer can request, resize, and free memory
as needed.
• Memory is allocated while the program is running (runtime).
• Programmer decides how much memory is needed and when.
Where it is stored:
• Allocated memory is stored in heap area.
Advantages of Dynamic Memory
✔ Flexible — Allocate as needed
✔ Prevents waste — exact memory requested
✔ Can grow/shrink using realloc()
✔ Useful when data size is unknown (e.g., user input, files)
Disadvantages
✘ Slower — runtime allocation
✘ Programmer must release memory (manual management)
✘ Risk of
• Memory leaks (not freeing memory)
• Dangling pointers (freeing too early)
• Segmentation faults
Memory Allocation Functions
In C, dynamic memory allocation is done using functions from the <stdlib.h> library. These functions
allow you to allocate, resize, and free memory at runtime.
Function Full Form Purpose Initialization Syntax
Allocates a single
malloc()
Memory No (contains ptr = (type*)
block of memory of
Allocation
given size (bytes) garbage values) malloc(size_in_bytes);
Allocates multiple
ptr = (type*)
calloc()
Contiguous blocks in a ✔ Yes (initializes calloc(n_elements,
Allocation continuous memory to 0) size_of_each);
region
Changes size of ptr = (type*)
realloc()
Re- realloc(old_ptr,
previously allocated
Allocation new_size_in_bytes);
memory
free()
Frees previously free(ptr);
allocated memory
File Handling
In C programming, files are used to store data permanently on secondary storage such as a hard
disk or SSD. When a program runs, variables and arrays store data in RAM (temporary). Once the
program ends, this data disappears. Files allow the program to save data even after execution,
making them essential for real-world applications like saving records, logs, or configuration settings.
File Modes
Mode Meaning
"r" Read only — file must exist
"w" Write — creates/overwrites file
"a" Append — writes at end of file
"r+" Read + write — no overwrite
"w+" Read + write — clears file
"a+" Read + append — preserves data