0% found this document useful (0 votes)
4 views36 pages

Module 3 Pointers

The document provides an overview of pointers in C programming, explaining their definition, usage, and importance in memory management. It covers topics such as pointer declaration, initialization, operators, dynamic memory allocation, and examples of modifying data through pointers. Additionally, it discusses the relationship between arrays, structures, and pointers, along with practical programming examples to illustrate these concepts.

Uploaded by

rajeshrdy66
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views36 pages

Module 3 Pointers

The document provides an overview of pointers in C programming, explaining their definition, usage, and importance in memory management. It covers topics such as pointer declaration, initialization, operators, dynamic memory allocation, and examples of modifying data through pointers. Additionally, it discusses the relationship between arrays, structures, and pointers, along with practical programming examples to illustrate these concepts.

Uploaded by

rajeshrdy66
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Established as per the Section 2(f) of the UGC Act, 1956

Approved by AICTE, COA and BCI, New Delhi

B24CI0201: Advanced C Programming and Applications

S c h o o l o f C o m p u t i n g a n d I n f o r m a t i o n Te c h n o l o g y

AY: 2025 (EVEN)


Pointers in C — What Are We Going to Learn & Why It Matters
Our Goals Today
➢ Understand what pointers are.
➢ Learn how pointers store and use memory addresses.
➢ Discover how to access and modify variables indirectly.
Why Should You Learn Pointers?
➢ Needed for:
Dynamic memory allocation (malloc, free)
Function arguments by reference
Building complex data structures (linked lists, trees, graphs)
➢ Understanding pointers = understanding how computers manage memory
Pointers in C
What is a Pointer? Why do we use it?
➢ A pointer is a variable that stores the memory address of another variable.

➢ Instead of holding the actual value of the data, a pointer holds the location in the computer's memory
where that data is stored.

Example:

➢ A regular variable is like a house with a name,

➢ The value of the variable is like the contents inside the house.

➢ A pointer is the address of that house.

➢ A pointer is like a piece of paper that contains the address of that house. It doesn't contain the contents
itself, but it tells you where to find them.
Declaring & Initializing Pointer Variables

Syntax: data_type *pointer_variable_name;

Example: int *p;

❖ Note what is the datatype of p -> int * (p is a pointer to an integer)

int num = 10;

int *p = #
Operators associated with Pointers
There are two fundamental operators associated with pointers:

How will you get the address of a variable x?


int x = 10;
int *p;
p = &x;
Address-of operator (&): This operator, when placed before a variable name,
returns the memory address of that variable. For example, if int x = 10;, then &x
would give you the memory address where the value 10 is stored.
Operators associated with Pointers
How to get the value using a pointer variable?
int x = 10;

int *p;

p = &x

int y = *p;
Dereference operator (*): This operator, when placed before a pointer variable,
accesses the value stored at the memory address held by the pointer. For example,
if int *p = &x;, then *p would give you the value 10.
Let’s write a program to C how it works:
#include <stdio.h>

int main() {
int a = 10; // Normal variable
int *p; //Pointer Variable (pointer declaration)
p = &a; // Pointer initialization

printf("Value of a: %d\n", a); // 10


printf("Address of a: %p\n", &a); // e.g., 0x7ffd23a4
printf("Value of p (address stored): %p\n", p); // Same as &a
printf("Value pointed by p: %d\n", *p); // 10

return 0;
}
Feature Normal Variable (a) Pointer Variable (p)
Stores The actual data value (10) The memory address of another variable
(address of a)
Memory Size Depends on its declared data type Fixed size based on system architecture (4
(4 bytes (for int)) bytes for 32-bit machine or 8 bytes for 64-bit
machine)
Accessing Value Directly using its name (Just a) Indirectly using the dereference operator (*)
(Use *p)
Address Address of the memory holding its Address of the memory holding the address of
value (&a) another variable (&p)
Declaration Syntax data_type variable_name data_type *pointer_name
(int a) (int *p)
Purpose Direct storage and manipulation of Dynamic memory management, pass by
data reference
Example int a = 5; printf("%d", a); int a = 5; int *p = &a; *p = 10; (now a becomes
10 because p points to it)
Program to modify the existing data value :
#include <stdio.h>
int main() {
int number = 5; //Variable Declaration
int *ptr; //Pointer Declaration
ptr = &number; //Pointer Initialisation
printf("Value of number: %d\n", number);
printf("Address of number: %p\n", &number);
printf("Value of ptr (address of number): %p\n", ptr);
printf("Value pointed to by ptr: %d\n", *ptr);
number = 25; //Modification
printf("Value of number: %d\n", number);
printf("Address of number: %p\n", &number);
printf("Value of ptr (address of number): %p\n", ptr);
printf("Value pointed to by ptr: %d\n", *ptr);
return 0;
}
Program to modify data Via Pointer :
#include <stdio.h>
int main() {
int number = 5; //Variable Declaration
int *ptr; //Pointer Declaration
ptr = &number; //Pointer Initialisation
printf("Value of number: %d\n", number);
printf("Address of number: %p\n", &number);
printf("Value of ptr (address of number): %p\n", ptr);
printf("Value pointed to by ptr: %d\n", *ptr);
number = 15; //Modification via variable
printf("Value of number: %d\n", number);
printf("Address of number: %p\n", &number);
printf("Value of ptr (address of number): %p\n", ptr);
printf("Value pointed to by ptr: %d\n", *ptr);
*ptr = 25; //Modification via Pointer
printf("\nValue of number after modification through ptr: %d\n", number);
printf("Address of number: %p\n", &number);
printf("Value of ptr (address of number): %p\n", ptr);
printf("Value pointed to by ptr after modification through ptr: %d\n", *ptr);
return 0;
}
Pass by Value and Pass by reference Recap:

Pass by Value Pass by Reference

void badswap(int a, int b) void goodswap(int *pa, int *pb)


{ {
int c; int c;
c=a; c=*pa;
a=b; *pa=*pb;
b=c; *pb=c;
} }
Arrays and Pointers:
• In C all array names are const pointer.

int a[3] = {0,1,2};

printf("%p %d %d\n",a,a[0],*a);

• a → is the address of the first element (&a[0])

• a[0] → is the first element of the array, i.e., 0

• *a → is the value at the address pointed to by a, i.e., *(&a[0]), which is again a[0], so the result is 0.

Note: you cannot do a++

• Because a is not a pointer variable, even though it behaves like one in some expressions.

• a is an array name, and in C, an array name is treated like a constant pointer.

• You can use it to access memory, but you cannot change it.

• So a++ means “increment the constant pointer,” which is not allowed.


Structures and Pointers:
typedef struct {

char name[50];

int age;

} Person;

Person p1;

Person *pp1=&p1;

How to access a member of structure member using pointers?

pp1->name same as (*pp1).name

pp1->age same as (*pp1).age


Program to swap two arrays using the function prototype:
#include <stdio.h> // Function to swap two arrays // Input array b
// Function to read an array printf("\nEnter elements for Array b:\n");
void read_array(int n, int arr[]) { void swap_array(int n, int a[], int b[]) { read_array(n,b);
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) { // Print before swapping
printf("Element [%d]: ", i); int temp = a[i]; printf("\nBefore swapping:\n");
scanf("%d", &arr[i]); a[i] = b[i]; printf("Array a: ");
} b[i] = temp; print_array(n, a);
} } printf("Array b: ");
// Function to print an array } print_array(n, b);
void print_array(int n, int arr[]) {
for (int i = 0; i < n; i++) { // Main function // Swap arrays
printf("%d ", arr[i]); int main() { swap_array(n, a, b);
} int n;
printf("\n"); printf("Enter the size of the arrays: "); // Print after swapping
} scanf("%d", &n); printf("\nAfter swapping:\n");
int a[n], b[n]; // Variable Length Arrays printf("Array a: ");
(VLAs) print_array(n,a);
// Input array a
printf("\nEnter elements for Array a:\n"); printf("Array b: ");
read_array(n,a); print_array(n,b);
return 0;
}
Program to swap two stings using the function prototype:
#include <stdio.h> // Main function // Swap the strings
#include <string.h> int main() { swap_strings(str1, str2);
char str1[100], str2[100];
// Function to read a string (no spaces // Print after swapping
allowed) // Read strings printf("\nAfter swapping:\n");
void read_string(char str[], int size) { printf("Enter first string: "); printf("String 1: ");
scanf("%s", str); // Reads until a space or read_string(str1, sizeof(str1)); print_string(str1);
newline
} printf("Enter second string: "); printf("String 2: ");
read_string(str2, sizeof(str2)); print_string(str2);
// Function to print a string
void print_string(char str[]) { // Print before swapping return 0;
printf("%s\n", str); printf("\nBefore swapping:\n"); }
} printf("String 1: ");
// Function to swap two strings print_string(str1); /*strcpy copies all characters from str1
void swap_strings(char str1[], char str2[]) { into temp, until the null character '\0'
char temp[100]; // Temporary buffer for printf("String 2: "); is found.*/
swapping print_string(str2);
strcpy(temp, str1);
strcpy(str1, str2);
strcpy(str2, temp);
}
Program to swap two structures using the function prototype:
#include <stdio.h> // Read details of a person int main() {
#include <string.h> void read_person(Person *p) { Person p1, p2;
printf("Enter name: ");
// Define structure scanf("%s", p->name); printf("Enter details for Person 1:\n");
typedef struct { printf("Enter age: "); read_person(&p1);
char name[50]; scanf("%d", &p->age);
int age; } printf("\nEnter details for Person 2:\n");
} Person; // Print details of a person read_person(&p2);
void print_person(Person *p) {
// Function prototypes printf("Name: %s, Age: %d\n", p->name, p- printf("\nBefore swap:\n");
void read_person(Person *p); >age); print_person(&p1);
void print_person(Person *p); } print_person(&p2);
void swap_person(Person *p1,
Person *p2); // Swap two persons swap_person(&p1, &p2);
void swap_person(Person *p1, Person *p2) {
Person temp = *p1; printf("\nAfter swap:\n");
*p1 = *p2; print_person(&p1);
*p2 = temp; print_person(&p2);
}
return 0;
}
Dynamic Memory Allocation and Pointers:
Why we need dynamic memory?
1. Fixed-size Array (Static Allocation): You must know the size at compile time.

Example: int a[100] = {1, 2, 3, 4, 5};

What it means:

• We are telling the compiler: "Reserve space for 5 integers."

• The size is fixed at compile time (before the program runs).

• You cannot change the size during the program.

Problems:

• Wastes memory if not fully used.

• Not flexible for user input (e.g., “how many students?”)


Dynamic Memory Allocation and Pointers:
Why we need dynamic memory?
2. Array with Compiler-Calculated Size:

Example: int a[] = {1, 2, 3};

What it means:

• The compiler counts the number of elements (3) and creates an array of size 3.

• Still, it's a fixed-size array created at compile time.

Problems:

• Size cannot be changed.


Dynamic Memory Allocation and Pointers:
Why we need dynamic memory?
3. Variable Length Array:

Example:

int n;

scanf("%d", &n);

int a[n]; // Variable Length Array

What it means:

• Size is based on user input, decided at runtime.

Problems:

• Cannot resize once declared.


Dynamic Memory Allocation and Pointers:
Dynamic Memory Allocation
• Allocate memory during program execution (runtime).

What it means:

• You ask the system to give memory while the program is running.

• malloc() allocates memory from the heap.

• You can allocate large sizes, and resize using realloc().

• But! You must free the memory using free() after use.

Example:
int *a;
int n;
scanf("%d", &n);
a = (int *)malloc(n * sizeof(int));
Dynamic Memory Allocation and Pointers:
Why do we use dynamic memory allocation?

• Use memory more efficiently by allocating only what is needed at runtime.

• Handle data structures whose size is not known at compile time or can change during
execution.

• Manage system resources effectively by allowing memory to be reused.

• Control the lifetime of allocated memory.


Dynamic Memory Allocation and Pointers:
malloc():
• malloc stands for Memory Allocation.

• Syntax: ptr = (data_type *)malloc(size_in_bytes);

• Example: int *ptr;

ptr= (int *)malloc(5 * sizeof(int));

• Allocates memory for 5 integers.

• Returns a pointer to the first byte of the allocated memory.

• Must typecast the return value in C.

• Allocated memory is uninitialized (may contain garbage values).

• If allocation fails, malloc() returns NULL (e.g., not enough memory).


Dynamic Memory Allocation and Pointers:
free():
• Releases memory previously allocated by malloc, calloc, or realloc.
• Prevents memory leaks (when memory is no longer used but not released).

• After using free(), set the pointer to NULL to avoid dangling pointers.

• Syntax: free(pointer);

• pointer should be the same pointer returned by a dynamic memory allocation function.

• Example: free(ptr);
ptr = NULL;
C program to demonstrate the usage of both malloc() and free()
#include <stdio.h> // Function Definitions
#include <stdlib.h> // Allocates memory dynamically and returns the pointer
// Function Prototypes int* create_array(int n) {
int* create_array(int n); return (int *)malloc(n * sizeof(int));
void initialize_array(int *arr, int n); }
void print_array(int *arr, int n); // Reads values into the array
void delete_array(int **arr); void initialize_array(int *arr, int n) {
int main() { for (int i = 0; i < n; i++) {
int n; printf("Element %d: ", i + 1);
int *arr; scanf("%d", &arr[i]);
printf("Enter the number of elements: "); }
scanf("%d", &n); }
arr = create_array(n); // Prints the array elements
if (arr == NULL) { void print_array(int *arr, int n) {
printf("Memory allocation failed!\n"); printf("The array elements are:\n");
return 1; for (int i = 0; i < n; i++) {
} printf("%d ", arr[i]);
initialize_array(arr, n); }
print_array(arr, n); printf("\n");
delete_array(&arr); // Pass address of pointer to safely set // Frees the memory and sets the pointer to NULL
it to NULL void delete_array(int **arr) {
return 0; free(*arr);
} *arr = NULL;
Linked list:
What Arrays Can't Do? Why Arrays Are Not Enough?
• When you create an array (e.g., int a[10];), the size is fixed.

• You cannot increase or decrease its size later without creating a new array, copying
everything over, and deleting the old one.

• Contiguous Memory Required: Arrays are stored in one continuous block of memory. If
a large enough block isn’t available, even malloc may fail. Linked lists use individual
nodes scattered in memory, so they don’t need one large continuous block.

• Insertion & Deletion Are Costly: To insert or delete an element in the middle of an array
you must shift all elements after it.
Linked list:
What if we want a list that can:

➢ Grow or shrink while the program runs?

➢ Add or remove elements anywhere in the list?

➢ Use only as much memory as we need (no fixed-size waste)?

This is where Linked Lists come in!


Linked list:
• A linked list is a linear data structure used to store elements of the
same data type but not in contiguous memory locations.
• It is a collection of nodes where each node contains a data field and a
pointer indicating the address of the next node.
• So only the current node in the list knows where the next element of the list is
stored.
• This dynamic nature allows linked lists to grow or shrink in size during program
execution.
• Analogy: Think of a treasure hunt. Each clue (node) tells you the location of the
next clue until you reach the final treasure (the end of the list).
Linked list:
How Linked Lists relate to Dynamic Memory:
• Each node is created using malloc when needed.

• You only use memory for nodes you actually have.

• When you remove nodes, you use free to return that memory.
Linked list:
Structure of a Linked List
• It’s a chain of nodes.

• Each node contains:

- Data: The value stored in the node (like an integer, name, etc.).

- Pointer to the next node in the list ((There can be multiple pointers for
different kind of linked list).

• The list grows dynamically, node by node.

• You can add or remove nodes without worrying about fixed size.
Linked list:
• Linked List is a recursive data structure in which any smaller part of it is also a linked list in itself.

typedef struct Node {


int data;
struct Node* next;
};
where,
• data: indicates the value stored in the node.
• next: is a pointer that will store the address of the next node in the sequence.
• The pointer to the first node of the list is called head.
Linked list:
Node structure:
• Represents a single element in the list.
• It holds the actual data and a pointer to the next node.
typedef struct Node {
int data; // The data stored in the node
struct Node* next; // A pointer to the next node in the list
} Node;
Linked list:
List structure:
• Acts as a "manager" for the entire linked list.
• It typically stores a pointer to the head (the first node) and sometimes other useful information
like the size of the list.
• This separation of concerns makes the code cleaner, easier to understand, and less prone to
errors.
typedef struct List {
Node* head; // A pointer to the first node in the list
int size; // (Optional but recommended) The number of nodes in the list
} List;
• head: This is the entry point to our linked list. If head is NULL, the list is empty.
• size: Keeping track of the size helps in quickly determining the number of elements without
having to traverse the entire list.
Linked List
#include <stdio.h>
#include <stdlib.h>
Node* createNode(int data) { void insertAtEnd(List* list, int data) {
typedef struct Node {
Node* newNode = (Node*)malloc(sizeof(Node)); Node* newNode = createNode(data);
int data;
if (newNode == NULL) { if (list->head == NULL) {
struct Node* next;
perror("Memory allocation failed for new node"); list->head = newNode;
} Node;
exit(EXIT_FAILURE); } else {
} Node* current = list->head;
typedef struct List {
newNode->data = data; while (current->next != NULL) {
Node* head;
newNode->next = NULL; current = current->next;
int size;
return newNode; }
} List;
} current->next = newNode;
void insertAtBeginning(List* list, int data) { }
List* createList() {
Node* newNode = createNode(data); list->size++;
List* newList = (List*)malloc(sizeof(List));
newNode->next = list->head; printf("Inserted %d at the end.\n", data);
if (newList == NULL) {
list->head = newNode; }
perror("Memory allocation failed for new list");
list->size++;
exit(EXIT_FAILURE);
printf("Inserted %d at the beginning.\n", data);
}
}
newList->head = NULL;
newList->size = 0;
return newList;

}
Node* current = list->head;
Linked List Node* prev = NULL;
void deleteFromBeginning(List* list) {
while (current->next != NULL) {
if (list->head == NULL) {
prev = current;
printf("List is empty. Nothing to delete from the beginning.\n");
current = current->next;
return; Node* findNode(const List* list, int data) {
}
} Node* current = list->head;
Node* temp = list->head; int deletedData = current->data;
int position = 0;
prev->next = NULL;
int deletedData = temp->data; while (current != NULL) {
free(current);
list->head = list->head->next; list->size--; if (current->data == data) {
free(temp); printf("Deleted %d from the end.\n", deletedData); printf("Found %d at position %d.\n",
} data, position);
list->size--;
printf("Deleted %d from the beginning.\n", deletedData); void displayList(const List* list) { return current;
if (list->head == NULL) { }
}
printf("List is empty.\n"); current = current->next;
void deleteFromEnd(List* list) {
return;
if (list->head == NULL) { position++;
printf("List is empty. Nothing to delete from the end.\n"); }
}
return; printf("List elements (%d nodes): ", list->size);
} printf("%d not found in the list.\n", data);
if (list->head->next == NULL) { Node* current = list->head;
return NULL;
int deletedData = list->head->data; while (current != NULL) {
}
free(list->head); printf("%d -> ", current->data);
list->head = NULL;
current = current->next;
list->size--;
printf("Deleted %d from the end (only node).\n", deletedData); }
return; printf("NULL\n");
}
}
Linked List

void destroyList(List* list) { int main() {


deleteFromBeginning(myList);
Node* current = list->head; List* myList = createList();
displayList(myList);
Node* nextNode; displayList(myList);
deleteFromEnd(myList);
while (current != NULL) { insertAtBeginning(myList, 10);
displayList(myList);
nextNode = current->next; displayList(myList);
deleteFromBeginning(myList);
free(current); insertAtEnd(myList, 20);
displayList(myList);
current = nextNode; displayList(myList);
deleteFromEnd(myList);
} insertAtBeginning(myList, 5);
displayList(myList);
free(list); displayList(myList);
deleteFromEnd(myList);
printf("List destroyed and memory freed.\n"); insertAtEnd(myList, 30);
displayList(myList);
} displayList(myList);
deleteFromBeginning(myList);
insertAtBeginning(myList, 1);
insertAtBeginning(myList, 100);
displayList(myList);
insertAtEnd(myList, 200);
findNode(myList, 10);
displayList(myList);
findNode(myList, 25);
destroyList(myList);
findNode(myList, 1);
return 0;
findNode(myList, 30);
}
printf("\n--- Deletion Operations ---\n");
Pointers in C — What We Have Learned
What is a pointer and how to declare one (int *p)
How to use & (address-of) and * (dereference) operators
Relationship between pointers and variables
Why It Matters
You now understand how to directly control and manipulate memory.
You’ve taken the first step towards mastering dynamic memory and data structures in C.

You might also like