Module – 3
POINTERS
What will you learn?
Pointers
Pointer Arithmetic
Constant Pointer
Generic Pointer
Pointer to Pointer
Arrays and Pointers
Pointer to Functions
Dynamic Memory Allocation
WHY POINTER?
Pointer in c are used for several reasons, offering
flexibility and control over memory and data. Here some key
reasons for using pointers.
Dynamic Memory Allocation
Efficient Array Handling
Direct Memory Access
Function Arguments
Building Complex Data structures(such as linked list, trees,
graphs etc…)
POINTER
A pointer is a derived data type variable that stores the memory
address of another variable located in computer memory.
It “points” to the location of data in memory, but does not directly
access the data itself.
Pointers are used to access and manipulate data stored in other
memory locations, providing a way to reference and manipulate
variables indirectly.
Syntax: -
data-type *pointer_name;
Datatype: The type of the data that the pointer will point to (e.g.,
int, float, char).
The asterisk * tells the compiler that the variable is pointer.
EXAMPLE:
1. int *ip // pointer to integer variable
2. float *fp; // pointer to float variable
3. double *dp; // pointer to double variable
4. char *cp; // pointer to char variable
EXAMPLE PROGRAM FOR
POINTERS:
#include <stdio.h>
int main()
{
int a = 10; // Declare an integer variable
int *p; // Declare a pointer to an integer
p = &a; // Assign the address of 'a' to the pointer 'p'
printf("Value of a: %d\n", a); // Output the value of 'a'
printf("Address of a: %p\n", &a); // Output the address of 'a'
printf("Value of p (Address stored in p): %p\n", p); // Output the
address stored in
'p'
printf("Value pointed to by p: %d\n", *p); // Output the value pointed
to by 'p’ (which is the value of 'a')
return 0;
INITIALIZATION OF POINTER
1. Pointer Initialization is the process of assigning address
of a variable to a pointer variable.
2. Pointer variable can only contain address of a variable of
the same data type.
3. In C language address operator & is used to determine
the address of a variable.
EXAMPLE:
#include<stdio.h>
ptr a
void main()
{
5772 10
int a = 10; 2000 5772
int *ptr; //pointer declaration
ptr = &a; //pointer initialization
printf(“%d”,ptr);
ptr =ptr+3;
printf(“%d”,ptr); output:1302925772
return 0; 1302925784
}
float a;
int *ptr;
ptr = &a; // ERROR, type mismatch
USING THE POINTER (OR) DEREFERENCING
POINTER
A Dereferenced pointer is what you get when you access
or modify the value at the memory address stored by the
pointer.
You use the * operator to dereference a pointer.
Once a pointer has been assigned the address of a variable,
to access the value of the variable, pointer is
dereferenced, using the indirection operator or
dereferencing operator or value at address operator.
EXAMPLE FOR DEREFERENCING POINTER
int a = 10;
int *p = &a; // p holds the address of 'a'
int value = *p; // Dereference p to get the value of ‘a’
Note: -
*p accesses the value stored at the address that p is
pointing to.
*p would give 10, since p points to a.
EXAMPLE PROGRAM FOR DEREFERENCE
POINTER
#include <stdio.h>
int main()
int a = 42; // Normal integer variable
int *p = &a; // Pointer p holds the address of a
printf("Pointer p: %p\n", (void*)p); // Outputs the memory address stored
in p
printf("Dereferenced pointer *p: %d\n", *p); // Outputs the value stored at
that address (42)
return 0;
Output: - Pointer p: 0x7fffe5365874 // Example address
DIFFERENCE BETWEEN POINTER AND
DEREFERENCE POINTER
SUMMARY
A pointer stores a memory address.
A dereferenced pointer accesses the value at that
memory address.
NULL POINTER
1. It is always a good practice to assign a NULL value to a
pointer variable in case if no address is assigned to it. A
pointer that is assigned NULL is called a null pointer.
2. The NULL pointer is a constant with a value of zero defined
in several standard libraries.
Syntax: -
int *ptr = NULL;
Note: -
Here, ptr is a pointer that is initialized to NULL,
meaning it doesn’t point to any valid memory location.
KEY CHARACTERISTICS OF A NULL
POINTER
1. It points to “nothing” or an invalid memory location.
2. Dereferencing a null pointer leads to undefined
behavior.(usually program crash)
3. It is not currently in use.
USE OF NULL POINTER
1. Null pointers are commonly used as flags to indicate the
absence of data, uninitialized pointers, or the end of linked
structures like linked lists or trees.
2. For example, in linked lists, a null pointer is used to indicate
the end of the list.
EXAMPLE PROGRAM FOR NULL POINTER
#include <stdio.h>
int main()
int *ptr = NULL; // Declare and initialize a null pointer
if (ptr == NULL)
printf("The pointer is null. It does not point to any memory
location.\n");
return 0;
}
GENERIC POINTER
A generic pointer is a pointer that can point to any data
type.
This is done using the void* type.
A void* pointer is a pointer that has no associated data type
with it.
A void pointer can hold address of any type and can be type-
casted to any type(int, char, float, etc.)
Syntax: -
void *ptr;
Here ptr is a pointer to void, which means it can point to any data
type.
CHARACTERISTICS OF GENERIC
POINTER
1. A generic pointer declared as void*.
2. It is used for writing general-purpose functions or for
dynamic memory management.
3. No type information: The pointer does not know the type
of data it is pointing to, so you must cast the pointer to the
correct data type before dereferencing it.
4. Cannot be dereferenced directly: Since the type is
unknown, the pointer must first be cast to a specific type
before dereferencing.
EXAMPLE PROGRAM FOR GENERIC
POINTER
#include <stdio.h> output: -
int main() { Pointer points to an integer: 10
int a = 10; Pointer points to a float: 5.50
float b = 5.5; Pointer points to a char: A
char c = 'A';
void *ptr; // Declare a generic pointer (void pointer)
ptr = &a; // Pointing to an integer
printf("Pointer points to an integer: %d\n", *(int*)ptr); // Cast to int* and dereference
ptr = &b; // Pointing to a float
printf("Pointer points to a float: %.2f\n", *(float*)ptr); // Cast to float* and dereference
ptr = &c; // Pointing to a char
printf("Pointer points to a char: %c\n", *(char*)ptr); // Cast to char* and dereference
return 0;
}
CONSTANT POINTER
A constant pointer(also known as “pointer constant”) is declared
with the const keyword after the *.
A constant pointer in C cannot change the address of the variable
to which it is pointing, i.e., the address will remain constant.
Therefore, we can say that if a constant pointer is pointing to
some variable, then it cannot point to any other variable.
Syntax: -
data_type *const pointer_name = &variable;
Here *const makes the pointer constant, meaning it can only point
to the address it is initialized with.
EXAMPLE PROGRAM FOR CONSTANT
POINTER
#include <stdio.h> output: - Value of a: 10
int main() New value of a: 15
int a = 10;
int b = 20;
int *const ptr = &a; // Constant pointer to 'a'
printf("Value of a: %d\n", *ptr); // Output: 10
*ptr = 15; // Allowed: Changing the value at the memory location 'a'
printf("New value of a: %d\n", *ptr); // Output: 15
// ptr = &b; // Error: Cannot change the address stored in ptr
return 0;
}
DIFFERENCE BETWEEN CONSTANT
POINTER AND POINTER TO CONSTANT
Constant pointer(data_type *const ptr): The pointer
address cannot change, but the value it points to can be
modified.
Pointer to constant(const data_type *ptr): The
pointer's address can change, but the value it points to
cannot be modified.
POINTER
ARITHMETIC
POINTER ARITHMETIC
C pointer is an address, which is a numeric value. Therefore, you can perform
arithmetic operations on a pointer just as you can a numeric value.
Pointer arithmetic offers a restricted set of arithmetic operators for manipulating
the addresses in pointers.
The following are the operations that can be performed over pointers.
1. We can add an integer value to a pointer.(ptr+1)
2. We can subtract an integer value from a pointer.(ptr-1)
3. We can compare two pointers if they point to the elements of the same array by
using relational operators.(<, >, == etc.)
4. We can subtract one pointer from another pointer if both point to the same array.
5. We can assign one pointer to another to another pointer provided both are of
same type.
BUT THE FOLLOWING OPERATIONS
ARE NOT POSSIBLE:
1. Addition of two pointers
2. Subtraction of one pointer from another pointer when they
do not point to the same array.
3. Multiplication of two pointers.
4. Division of one pointer by another pointer.
EXAMPLE PROGRAM FOR POINTER
#include <stdio.h>
ARITHMETIC
int main() {
int arr[] = {10, 20, 30, 40, 50};
int *ptr = arr; // Pointer to the first element of the array
printf("Pointer points to: %d\n", *ptr); // Output: 10
ptr++; // Increment the pointer (move to the next element)
printf("After incrementing, pointer points to: %d\n", *ptr); // Output: 20
ptr += 2; // Add 2 to the pointer (move forward by 2 elements)
printf("After adding 2, pointer points to: %d\n", *ptr); // Output: 40
ptr--; // Decrement the pointer (move to the previous element)
printf("After decrementing, pointer points to: %d\n", *ptr); // Output: 30
int *start_ptr = arr; // Calculate the difference between two pointers
int diff = ptr - start_ptr;
printf("Difference between start_ptr and ptr: %d\n", diff); // Output: 3
return 0; }
POINTER TO A
POINTER
Pointer is also a variable, it is also allocated with memory space
and its address also is retrievable.
The address of the pointer variable itself can also be stored in
another variable.
The variable, which can store the address of a pointer variable
itself, is termed a pointer to pointer.
Syntax:
data-type **variable;
The usage of double * before the pointer variable name are
indicate that the variable is a pointer to a pointer to a variable of
type data-type.
EXAMPLE:
app ap a
int a = 10;
int *ap;
2000 1000 10
int **app; 3000 2000 1000
ap = &a;
app=≈
printf(“Address of a = %u\n”,ap); // 1000
printf(“Address of ap = %u\n”,app); // 2000
printf(“Value of a through ap = %d \n”, *ap); // *(1000) =
10
printf(“Value of a through app = %d \n”, **app);
**(2000) => *(*(2000)) => *(1000) => 10
POINTERS AND
ARRAYS
POINTERS AND
ARRAYS
1. A pointer array (also called an "array of pointers") is an array
where each element is a pointer.
2. When an array is declared, the compiler allocates a base
address and sufficient amount of memory to contain all the
elements of the array in continuous memory locations.
3. The base address is the location of the first element of the array
denoted by a[0].
4. The compiler also defines the array name as constant pointer to
the first element.
Syntax: -
data_type *array_name[size];
EXAMPLE: -
int a [5] = {1, 2, 3, 4, 5};
Here if the base address is 1000 for “a” and if integer occupies 4
bytes then the five elements requires 20 bytes as shown below.
element a[0] a[1] a[2] a[3] a[4]
value 1 2 3 4 5
address 1000 1002 1004 1006 1008
The name of the array is “a” and it is defined as a
constant pointer pointing to the first element of the array and it is
a[0] whose base address is 1000 becomes the value of “a”. It is
represented as
a = &a[0] = 1000;
If p is a pointer of integer type then p to point the array a is given by the assignment
statement
element a[0] a[1] a[2] a[3] a[4]
p = a;
value 1 2 3 4 5
which is equivalent to address 1000 1002 1004 1006 1008
p = &a[0]; P1 P2
int X=P2 – P1
Now it is possible to access every value of a using p++ to move from one element to
another element as
P is equal to &a[0] i.e.1000 and *p gives value at address 1000 i.e. 1
P+1 is equal to &a[1] i.e. 1002 and *(p+1) gives value at address 1002 i.e. 2
P+2 is equal to &a[2] i.e. 1004 and *(P+2) gives value at address 1004 i.e. 3
P+3 is equal to &a[3] i.e. 1006 and *(P+3) gives value at address 1006 i.e. 4
P+4 is equal to &a[4] i.e. 1008 and *(P+4) gives value at address 1008 i.e. 5
CONTINUED.,
In one dimensional array “a” the expression, *(a+i) or *(p+i)
represents ith element in array.
an element in a two dimensional array can be represented by the
pointer expression as *(*(a+i)+j) or *(*(p+i)+j)
#include <stdio.h>
int main()
int arr[3]={20,30,40};
int *p;
p=arr; // Assigning the base address of array arr to pointer p
printf("Value of a: %d\n", *(arr+1)); // Output: 30
printf("Value of b: %d\n", *(p+2)); // Output: 40
return 0;
}
EXAMPLE PROGRAM ARRAY OF POINTERS TO
INTEGERS
#include <stdio.h>
int main() {
int a = 10, b = 20, c = 30;// Declare an array of 3 integer pointers
int *arr[3];
// Assign the addresses of variables to the array
arr[0] = &a;
arr[1] = &b;
arr[2] = &c;
// Access the values through the array of pointers
printf("Value of a: %d\n", *arr[0]); // Output: 10
printf("Value of b: %d\n", *arr[1]); // Output: 20
printf("Value of c: %d\n", *arr[2]); // Output: 30
return 0;
}
POINTERS TO
FUNCTIONS
POINTERS TO
FUNCTIONS
1. In C, pointers to functions are pointers that store the address
of a function.
2. This allows functions to be passed as arguments to other
functions, returned from functions, or stored in arrays.
3. Function pointers enable dynamic function calls, providing
flexibility in how functions are invoked during runtime.
Syntax: - return_type (*pointer_name)(parameter_types);
retrun_type : The return type of the function.
Pointer_name : The name of the function pointer.
Parameter_types: The types of parameters the function takes.
EXAMPLE PROGRAM POINTERS TO FUNCTIONS
#include <stdio.h>
// Function declarations
int add(int a, int b)
{
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
int main()
{
// Declare a function pointer
int (*operation)(int, int);
// Point to the 'add' function
operation = &add;
printf("Result of add: %d\n", operation(10, 5)); // Calls add(10, 5)
// Point to the 'subtract' function
operation = &subtract;
printf("Result of subtract: %d\n", operation(10, 5)); // Calls subtract(10, 5)
return 0;
}
BENEFITS OF USING POINTER TO
FUNCTIONS
Callback Functions: Useful in scenarios like event
handling or custom comparison functions (e.g., in sorting
algorithms).
Dynamic Function Allocation: Allows choosing the
function to call at runtime, which adds flexibility.
Array of Function Pointers: You can store multiple
function pointers in an array and call different functions
using the array index.
DYNAMIC MEMORY
ALLOCATION
MEMORY ALLOCATION
There are two types of memory allocations: static allocation
and dynamic allocation
1. Static allocation refers to allocation of memory for a
variable at compile time. They need declarations and
definitions specified in the source program. The number of
bytes reserved cannot be changed.
2. Dynamic allocation refers to allocation of memory for a
variable at run time. They use predefined functions to
allocate and de-allocate memory for data while the program
is running. Memory is allocated from heap through pointer.
MEMORY ALLOCATION
There are two types of memory allocations: static allocation
and dynamic allocation
1. Static allocation refers to allocation of memory for a
variable at compile time. They need declarations and
definitions specified in the source program. The number of
bytes reserved cannot be changed.
2. Dynamic allocation refers to allocation of memory for a
variable at run time. They use predefined functions to
allocate and de-allocate memory for data while the program
is running. Memory is allocated from heap through pointer.
DYNAMIC MEMORY
MANAGEMENT
Consider an array
int marks [100];
DYNAMIC MEMORY ALLOCATION
FUNCTIONS
The process of allocating memory at run time is known as
dynamic memory allocation. The C programming does not have
this function. But it offers it through memory management
functions. The memory management functions are used to allocate
and de-allocate storage during program execution. The functions
are
1. malloc()
2. calloc()
3. realloc()
4. free()
MALLOC()
malloc( ) function is used to allocate space in memory during the execution
of the program.
This function is used to allocate single block of memory.
It does not initialize the memory allocated during execution.
It carries garbage value.
It returns null pointer if it couldn’t be able to allocate requested amount of
memory.
Syntax: -
void * malloc(size_t size);
Size: The number of bytes to allocate.
Returns: A pointer of type void* , which can be cast to any datatype.
EXAMPLE OF
MALLOC()
Example: -
int *ptr;
ptr = (int*) malloc(5 * sizeof(int)); // Allocates memory for 5 integers
if (ptr == NULL)
printf("Memory allocation failed\n");
It is also used to allocate storage for complex data such as
structures.
CALLOC()
Calloc() stands for continuous allocation.
This function is used to allocate multiple blocks of memory.
It is used to store data types such as arrays and structures.
It allocates storage for multiple blocks and initializes them all to zero
and the pointer will point to the first byte of the first block. Here all
blocks are same size.
Syntax: -
void* calloc(size_t num, size_t size);
Num: Number of elements to allocate.
Size: Size of each element.
Returns: A pointer of type void*, similar to malloc( ), which can be
cast to any data type.
EXAMPLE FOR
CALLOC()
Example: -
int *ptr;
ptr = (int*) calloc(5, sizeof(int)); // Allocates memory for 5
integers and initializes to 0
if (ptr == NULL)
printf("Memory allocation failed\n");
}
REALLOC()
Realloc() stands for reallocation.
It changes the size of previously allocated memory (either using
malloc() or calloc() ).
If the new size is larger, the additional memory will not be
initialized.
If the new size is smaller, the excess memory is freed.
Syntax:
void* realloc(void* ptr, size_t newsize);
Ptr: Pointer to the previously allocated memory.
Newsize: The new size for the memory block.
Returns: A pointer to the reallocated memory, which may or
may not be the same as the original pointer.
EXAMPLE FOR
REALLOC()
Example: -
int *ptr;
ptr = (int*) malloc(5 * sizeof(int));
ptr = (int*) realloc(ptr, 10 * sizeof(int)); // Reallocates
memory to hold 10
integers
if (ptr == NULL)
printf("Reallocation failed\n");
}
FREE()
Free() is used to deallocate memory that previously
allocated by malloc(), calloc(), or realloc().
Whenever a variable is no longer then such variables
memory is released. It is done by using free function.
Syntax : -
void free(void *ptr);
Ptr: Pointer to the memory blocked to be freed. If PTR
is null no action is required.
EXAMPLE FOR FREE()
Example:
int *ptr;
ptr = (int*) malloc(5 * sizeof(int));
// Use the allocated memory...
free(ptr); // Frees the allocated memory
SUMMARY
Malloc() : Allocates memory without initialization.
Calloc() : Allocates and initializes memory to zero.
Realloc() : Resizes previously allocated memory.
Free() : Frees the allotted memory.
Each of these functions plays a crucial role in
managing memory dynamically during the execution of a
program.
Program to allocate memory for an array dynamically, store and access its
values.
#include <stdio.h>
#include<stdlib.h>
int main()
{
int *a, i, n;
printf("Enter the size of the array");
scanf("%d",&n);
a = (int *)calloc(n,sizeof(int));
printf("Enter elements into the array");
for(i=0; i<n; i++)
scanf("%d",&a[i]);
printf("Elements of the array");
for(i=0;i<n;i++)
printf("%d",a[i]);
free(a);
}
DIFFERENCE BETWEEN STATIC MEMORY
ALLOCATION AND DYNAMIC MEMORY
ALLOCATION
FIND THE OUTPUTS
#include <stdio.h>
int main() {
int a[] = {1, 2, 3, 4, 5};
int *ptr = a;
printf("%d", *(ptr + 3));
return 0;
}
57
#include <stdio.h>
int main() {
int x = 10, *y;
y = &x;
*y = *y + 5;
printf("%d", x);
return 0;
}
58
#include <stdio.h>
int main() {
int arr[] = {10, 20, 30, 40};
int *ptr = arr;
ptr++;
printf("%d", *ptr);
return 0;
}
59
Which of the following statements about C pointers is
incorrect?
(a) Pointers can be used to store the address of variables.
(b) Pointer arithmetic is allowed in C.
(c) A pointer can be dereferenced to access the value at the
memory location it points to.
(d) You can assign the address of a constant directly to a
pointer and modify the value of the constant.
Answer:
60
#include <stdio.h>
int main() {
int a = 5, b = 10;
int *p = &a, *q = &b;
*p = *q;
printf("%d %d", a, b);
return 0;
}
61