MODULE 3
What is a Pointer in C?
A pointer is a variable that stores the memory address of another variable.
Why use Pointers?
• To directly access and modify memory.
• To pass large data to functions efficiently.
• To do dynamic memory allocation.
• To work with arrays, strings, and data structures.
Basic Terms:
Term Meaning
* Used to declare a pointer or dereference (get value from address)
& Used to get the address of a variable
Simple Example:
#include <stdio.h>
int main() {
int a = 10;
int *p; // Declaring pointer to int
p = &a; // Storing address of a into pointer p
printf("Value of a: %d\n", a); // 10
printf("Address of a: %p\n", &a); // e.g., 0x7ffee7...
printf("Value of p (address of a): %p\n", p); // Same as above
printf("Value at p (i.e., a): %d\n", *p); // 10
return 0;
Operations on Pointers
1. Declaration
int *ptr; // pointer to int
2. Initialization
int a = 5;
ptr = &a; // stores address of a in ptr
3. Dereferencing
printf("%d", *ptr); // prints value at the address (i.e., value of a)
4. Pointer Arithmetic
Operation Meaning
ptr + 1 Move to next memory location (depends on data type)
ptr++ Same as ptr = ptr + 1
ptr - 1 Move to previous memory location
Example:
int arr[3] = {10, 20, 30};
int *p = arr;
printf("%d\n", *p); // 10
printf("%d\n", *(p + 1)); // 20
printf("%d\n", *(p + 2)); // 30
Summary
• int *p; → Declares a pointer to int
• p = &a; → Stores address of a in p
• *p → Value at the memory location p
• Pointer arithmetic is used to move between elements in memory (like arrays)
What is "Passing Pointers to Functions"?
Normally, when we give a value to a function, only a copy is sent. So, any changes made in the
function do not affect the original value.
But when we pass a pointer (i.e., the address of a variable), the function can directly access and
change the original variable.
Why Should We Use Pointers in Functions?
1. To Change Original Values
With pointers, you can update variables inside a function, and the changes will be visible
outside the function too.
2. Saves Memory
Instead of copying big data (like arrays), we just send the address.
3. Can Return Multiple Values
Functions can change many variables using pointers.
Example to Understand: Swapping Two Numbers
Without Pointers (Doesn’t Work)
#include <stdio.h>
void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
int main() {
int x = 5, y = 10;
swap(x, y);
printf("x = %d, y = %d\n", x, y); // Output: x = 5, y = 10 (No change)
Here, a and b are just copies of x and y. So, the original values don't change.
With Pointers (Works Perfectly)
#include <stdio.h>
void swap(int *a, int *b) {
int temp = *a; // Get value from address
*a = *b; // Change value at address
*b = temp;
int main() {
int x = 5, y = 10;
swap(&x, &y); // Pass address of x and y
printf("x = %d, y = %d\n", x, y); // Output: x = 10, y = 5 (Swapped!)
What Happened?
• &x and &y send the addresses of x and y.
• Inside the function, *a and *b directly change the real values of x and y.
What is Dynamic Memory Allocation?
Dynamic memory allocation means giving memory during program running time.
You use it when you don’t know in advance how much memory you will need.
Why is it Useful?
• You can create memory when needed
• Saves memory by not wasting space
• Helps create flexible programs
Functions Used (from <stdlib.h>):
Function What it does
malloc() Gives memory (empty)
calloc() Gives memory (filled with 0)
realloc() Changes the size of memory
free() Releases (frees) the memory
Examples (Very Simple)
1. malloc() – allocate memory
#include <stdio.h>
#include <stdlib.h>
int main() {
int *p;
p = (int *)malloc(3 * sizeof(int)); // gives memory for 3 integers
p[0] = 10;
p[1] = 20;
p[2] = 30;
printf("%d %d %d", p[0], p[1], p[2]);
free(p); // release memory
return 0;
2. calloc() – memory + zero
#include <stdio.h>
#include <stdlib.h>
int main() {
int *p;
p = (int *)calloc(3, sizeof(int)); // 3 integers, all 0
printf("%d %d %d", p[0], p[1], p[2]); // prints: 0 0 0
free(p);
return 0;
3. realloc() – change size of memory
#include <stdio.h>
#include <stdlib.h>
int main() {
int *p = (int *)malloc(2 * sizeof(int));
p[0] = 1;
p[1] = 2;
p = (int *)realloc(p, 4 * sizeof(int)); // now space for 4 numbers
p[2] = 3;
p[3] = 4;
printf("%d %d %d %d", p[0], p[1], p[2], p[3]);
free(p);
return 0;
free() – to release memory
free(p);
Always use free() after using malloc, calloc, or realloc.
Summary (One Line Each)
• malloc() → gives memory (garbage values)
• calloc() → gives memory (filled with zero)
• realloc() → changes the memory size
• free() → gives memory back to system
What is the Relationship Between Arrays and Pointers in C?
In C, arrays and pointers are closely connected, because:
The name of an array is actually a pointer to its first element in memory.
This means:
arr == &arr[0]
*arr == arr[0]
Let's Understand Step-by-Step
1. Array Basics
When we write:
int arr[3] = {10, 20, 30};
It means:
• arr[0] = 10
• arr[1] = 20
• arr[2] = 30
Here, arr is the array name, but internally it acts like a constant pointer pointing to the first
element arr[0].
2. Pointer Basics
int *ptr;
ptr = arr; // or ptr = &arr[0];
• Now ptr points to the first element of the array.
• You can access array elements using pointer notation:
*(ptr + 0) == arr[0]
*(ptr + 1) == arr[1]
*(ptr + 2) == arr[2]
3. Pointer and Array Notations are Interchangeable
In C, the following expressions all give the same value:
Expression Meaning
arr[i] value at index i
*(arr + i) same as arr[i]
ptr[i] if ptr = arr;, this is valid
*(ptr + i) same as ptr[i]
So, array notation and pointer notation are just different ways of accessing the same memory.
Example Program
#include <stdio.h>
int main() {
int arr[4] = {5, 10, 15, 20};
int *ptr = arr; // or ptr = &arr[0];
for (int i = 0; i < 4; i++) {
printf("Using arr[%d] = %d\t", i, arr[i]);
printf("Using *(ptr + %d) = %d\n", i, *(ptr + i));
return 0;
Output:
Using arr[0] = 5 Using *(ptr + 0) = 5
Using arr[1] = 10 Using *(ptr + 1) = 10
Using arr[2] = 15 Using *(ptr + 2) = 15
Using arr[3] = 20 Using *(ptr + 3) = 20
4. Array Name is a Constant Pointer
int arr[3] = {1, 2, 3};
arr++; // Not allowed (Error)
• You cannot change the array name because it's a constant pointer.
• But if you assign it to another pointer:
int *ptr = arr;
ptr++; // This is allowed
5. Why is This Relationship Useful?
Feature Benefit
Arrays act like pointers Easy to pass arrays to functions
Feature Benefit
Pointer arithmetic Loop through array using *(ptr + i)
Saves memory Only the address is passed, not full array
1. Single-Dimensional Array using Pointers
#include <stdio.h>
int main() {
int arr[5] = {10, 20, 30, 40, 50};
int *ptr = arr; // pointer points to the first element of array
printf("Elements using pointer:\n");
for(int i = 0; i < 5; i++) {
printf("%d ", *(ptr + i)); // pointer notation
return 0;
Output:
Elements using pointer:
10 20 30 40 50
2. Multi-Dimensional Array (2D) using Pointers
#include <stdio.h>
int main() {
int arr[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
int *ptr = &arr[0][0]; // pointer to first element of 2D array
printf("2D Array elements using pointer:\n");
for (int i = 0; i < 2 * 3; i++) {
printf("%d ", *(ptr + i));
return 0;
Output:
2D Array elements using pointer:
123456