0% found this document useful (0 votes)
7 views

POINTERS in C Programming Language

The document provides a comprehensive overview of pointers in the C programming language, explaining their definition, declaration, initialization, and various operations. It covers pointer arithmetic, usage with arrays, strings, functions, and structures, along with advanced concepts like null pointers and pointer to pointer. Additionally, it includes practical problems for practice to reinforce understanding of pointer concepts.

Uploaded by

Dattu Gollapinni
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

POINTERS in C Programming Language

The document provides a comprehensive overview of pointers in the C programming language, explaining their definition, declaration, initialization, and various operations. It covers pointer arithmetic, usage with arrays, strings, functions, and structures, along with advanced concepts like null pointers and pointer to pointer. Additionally, it includes practical problems for practice to reinforce understanding of pointer concepts.

Uploaded by

Dattu Gollapinni
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 31

FEBRUARY 11, 2025

UNDERSTANDING
POINTERS IN C PROGRAMMING LANGUAGE

VAMSI KRISHNA VAKA


Pointers in C: A Detailed Explanation

What is a Pointer?

A pointer is a variable that stores the memory address of another variable. Instead of storing data
directly, a pointer stores the location where the data is stored. The pointer variable can be of type int,
char, array, function, or any other pointer. The size of the pointer depends on the architecture.

Declaration and Initialization of Pointers

A pointer is declared using the * (asterisk) symbol.

Code example:

#include <stdio.h>
int main()
{
int num = 26; // Normal integer variable
int *ptr = &num; // Pointer storing the address of variable 'a' and ‘&’ is called as Addressof Operator
int **rptr = ptr;
printf("Value of num: %d\n", num);
printf("Address of num: %p\n", &num);
printf("Value stored in pointer ptr: %p\n", ptr);
printf("Value pointed by ptr: %d\n", *ptr); // Dereferencing Operator
printf("Value stored in pointer rptr: %p\n", *rptr);
printf("Value pointed by **rptr: %d\n", **rptr);
return 0;
}

Pointer Operators
1. & (Address-of Operator) → Gets the address of a variable.
2. * (Dereference Operator) → Accesses the value stored at the pointer’s address.

Key Reasons for Using Pointers:


1. Efficient Memory Management (dynamic allocation)
2. Passing by Reference (avoids data copying, better performance)
3. Direct Hardware/Memory Access (essential in embedded systems)
4. Building Data Structures (linked lists, trees, etc.)
5. Facilitating DMA (for low-level memory operations)
6. Enabling Multi-level Indirection (complex data management)
7. Performance Optimization (faster execution)
8. System-Level Interfacing (interacting with OS-level APIs)

Complete List of Pointer Concepts in C


• Pointers are a powerful feature in C, and they are used extensively across various concepts like arrays,
functions, strings, structures, dynamic memory, and more. Below is a comprehensive list of all pointer-
related concepts categorized by their use cases.

1. Basic Pointer Concepts


• These are fundamental pointer operations.
Concept Description Example
Pointer Declaration Declaring a pointer variable. int *ptr;
Pointer Initialization Assigning an address to a pointer. ptr = &var;
Dereferencing a Pointer Accessing the value stored at the address. *ptr = 10;
Null Pointer Pointer that does not point to any valid memory. int *ptr = NULL;
Pointer to Pointer Pointer that stores the address of another pointer. int **pptr = &ptr;

2. Pointer Arithmetic
• Used to navigate through memory.
Concept Description Example
Increment (ptr++) Moves pointer to next element. ptr++;
Decrement (ptr--) Moves pointer to previous element. ptr--;
Addition (ptr + n) Moves pointer forward by n elements. ptr = ptr + 2;
Subtraction (ptr - n) Moves pointer backward by n elements. ptr = ptr - 1;
Pointer Difference Finds the number of elements between two pointers. int diff = ptr2 - ptr1;

3. Pointers and Arrays


• Used to manipulate arrays efficiently.
Concept Description Example
Array Name as Pointer arr acts as a pointer to its first element. int *ptr = arr;
Accessing Array Elements Using pointer arithmetic instead of indexing. *(arr + i)
Pointer to Array Pointer storing address of an array. int (*ptr)[5] = &arr;
Array of Pointers An array that stores multiple pointer addresses. int *arrPtr[5];

4. Pointers and Strings


• Used to manipulate character arrays (char strings).
Concept Description Example
String as a Pointer String literals are stored as pointers. char *str = "Hello";
Pointer Iteration over String Move through a string using pointer arithmetic. while (*str) { str++; }
String Modification Using Pointers Change characters using pointer access. *(str + 1) = 'a';

5. Pointers and Functions


• Used to pass values efficiently.
Concept Description Example
Passing Pointer to Function Allows modification of original variable. void change(int *p);
Returning Pointer from Function Function can return a dynamically allocated pointer. int* func();
Function Pointer Stores the address of a function. int (*funcPtr)(int, int);
Array of Function Pointers Stores multiple function addresses. int (*fptr[3])();

6. Pointers and Structures


• Used in advanced data structures like linked lists.
Concept Description Example
Pointer to Structure Used to access members of a structure. struct Student *ptr;
Accessing Members using Arrow (->) Shortcut for (*ptr).member. ptr->id = 10;
Structure Containing a Pointer Structure has a pointer member. struct Student { int *marks; };
Array of Structure Pointers Array storing multiple struct pointers. struct Student *arr[5];

7. Advanced Pointer Concepts


• Used in dynamic memory management and system programming.
Concept Description Example
Generic pointer that can store any data type
Void Pointer void *ptr;
address.
Dangling Pointer Pointer that points to a deleted memory location. free(ptr);
Uninitialized pointer pointing to unknown
Wild Pointer int *ptr;
memory.
Pointer itself is constant (cannot change
Constant Pointer (int *const ptr) ptr = &a;
address).
*ptr = 5; // Not
Pointer to Constant (const int *ptr) Data pointed by the pointer is constant.
allowed
Constant Pointer to Constant ptr = &b; // Not
Both pointer and data are constant.
(const int *const ptr) allowed

Basic Pointer concepts:


1. Pointer Declaration and Initialization
Syntax:
data_type *pointer_name;

• data_type: Type of data the pointer will point to (e.g., int, char, float).
• *: Denotes that the variable is a pointer.
• pointer_name: Name of the pointer variable.

Example:

#include <stdio.h>
int main()
{
int num = 10;
int *ptr; // Pointer declaration
ptr = &num; // Pointer initialization
printf("Address of num: %p\n", &num);
printf("Address stored in ptr: %p\n", ptr);
printf("Value of num using pointer: %d\n", *ptr); // Dereferencing

return 0;
}
Output:
Address of num: 0x7ffc12345678
Address stored in ptr: 0x7ffc12345678
Value of num using pointer: 10
Here:
• ptr stores the address of num.
• *ptr accesses the value at that address.
Note: An uninitialized pointer contains a random garbage address. If you accidentally dereference it, your
program may crash. It is Good Practice to Initialize with NULL.
Ex: int *ptr = NULL;

Memory Representation
Consider this memory layout:
Variable Value Address (Hex)
num 10 0x1000
ptr 0x1000 (Address of num) 0x2000
When ptr = &num;, the pointer stores the memory address of num.

2. Dereferencing a Pointer
Dereferencing means accessing the value stored at the memory location a pointer is pointing to.
Example:
#include <stdio.h>
int main()
{
int a = 20;
int *p = &a;
printf("Value of a: %d\n", *p); // Dereferencing
*p = 30; // Modifying value using pointer
printf("New value of a: %d\n", a);
return 0;
}
Output:
Value of a: 20
New value of a: 30
Explanation:
• *p accesses a's value.
• Modifying *p changes a's value directly.

3. Null Pointer
A null pointer does not point to any valid memory location. This prevents accessing invalid memory.
Example:

#include <stdio.h>
int main()
{
int *ptr = NULL; // Null pointer
if (ptr == NULL)
{
printf("Pointer is NULL, cannot dereference it!\n");
}
return 0;
}
Output:
Pointer is NULL, cannot dereference it!
Dereferencing a NULL pointer leads to segmentation faults.

4. Pointer to Pointer (Double Pointer)


A pointer to pointer stores the address of another pointer.
Example:
#include <stdio.h>
int main()
{
int x = 50;
int *p = &x; // Pointer to x
int **q = &p; // Pointer to pointer
printf("Value of x: %d\n", **q); // Dereferencing twice
return 0;
}
Output:
Value of x: 50
Here:
• p stores &x.
• q stores &p.
• **q accesses x's value.

Memory Representation of Pointer to Pointer


Variable Value Address
x 50 0x1000
p 0x1000 0x2000
q 0x2000 0x3000

Problems for Practice


Problem 1: Pointer Basics
Write a program that:
1. Declares an integer and assigns a value.
2. Declares a pointer and assigns it the address of the integer.
3. Prints:
o The integer value using both normal variable and pointer.
o The address of the integer.
o The address stored in the pointer.

Problem 2: Modify Value Using Pointers


Write a program that:
1. Declares an integer and initializes it.
2. Creates a pointer that points to it.
3. Changes the integer value using the pointer.
4. Prints the updated value.

Problem 3: Pointer to Pointer


Write a program that:
1. Declares an integer and initializes it.
2. Creates a pointer pointing to that integer.
3. Creates another pointer that stores the first pointer’s address.
4. Prints the integer value using both pointers.
Pointer Arithmetic in C
• Pointer arithmetic allows performing operations like addition, subtraction, and comparison on
pointers. Since pointers store addresses, manipulating them changes where they point in memory.
• Pointer arithmetic allows you to navigate through memory efficiently by modifying the value of a pointer
to access different memory locations. In embedded systems, this is especially useful when working
with arrays, buffers, or memory-mapped registers.

Types of Pointer Arithmetic

1. Increment (ptr++)
• Description: This operation increments the pointer, moving it to the next memory location. The pointer
points to the next element in the array or memory block.
• Example:
int arr[5] = {10, 20, 30, 40, 50};
int *ptr = arr;
ptr++; // Points to arr[1]

2. Decrement (ptr--)
• Description: This operation decrements the pointer, moving it to the previous memory location. The
pointer points to the previous element in the array or memory block.
• Example:

int arr[5] = {10, 20, 30, 40, 50};


int *ptr = &arr[3];
ptr--; // Points to arr[2]

3. Addition (ptr + n)
• Description: You can add an integer to a pointer, which moves the pointer forward by 'n' elements,
where each element size is based on the data type the pointer is pointing to.
• Example:

int arr[5] = {10, 20, 30, 40, 50};


int *ptr = arr;
ptr = ptr + 2; // Points to arr[2], which is 30

4. Subtraction (ptr - n)
• Description: Subtracting an integer from a pointer moves the pointer backward by 'n' elements.
• Example:

int arr[5] = {10, 20, 30, 40, 50};


int *ptr = &arr[4];
ptr = ptr - 1; // Points to arr[3], which is 40

5. Pointer Difference
• Description: This operation computes the difference between two pointers that point to elements in
the same array or memory block. The result is the number of elements between the two pointers.
• Example:

int arr[5] = {10, 20, 30, 40, 50};


int *ptr1 = arr;
int *ptr2 = &arr[3];
int diff = ptr2 - ptr1; // diff = 3, because ptr2 is 3 elements ahead of ptr1

6. Pointer Comparison
• Description: Pointers can be compared using relational operators (<, >, ==, etc.) to check their relative
positions in memory. It is used to compare the addresses they hold.
• Example:

int arr[5] = {10, 20, 30, 40, 50};


int *ptr1 = arr;
int *ptr2 = &arr[3];
if (ptr1 < ptr2)
{
// ptr1 is pointing to an earlier memory location than ptr2
}

Practice Problems:
1. Array Traversal using Pointer Arithmetic:
o Given an array of 10 integers, use pointer arithmetic to print all the elements of the array.
o Example array: {5, 10, 15, 20, 25, 30, 35, 40, 45, 50}
2. Pointer Arithmetic with String:
o Given a string "Hello", use pointer arithmetic to print each character one by one.
o Example output: H e l l o
3. Find Difference between Two Pointers:
o Given two pointers pointing to elements in an array, find how many elements are between
them using pointer subtraction.
4. Pointer Comparison:
o Given two pointers ptr1 and ptr2 pointing to different elements in an array, compare their
values using relational operators and print which one points to the higher memory
location.
5. Dynamic Array Creation and Pointer Arithmetic:
o Allocate memory for an array of integers dynamically using malloc. Use pointer arithmetic
to fill and print the values of the array.
Problems:

1. Increment (ptr++)
When you increment a pointer, it moves to the next memory location of the type it points to.

#include <stdio.h>
int main()
{
int arr[] = {10, 20, 30};
int *ptr = arr;

printf("Address before increment: %p\n", ptr);


ptr++; // Moves to the next integer (4 bytes forward)
printf("Address after increment: %p\n", ptr);

return 0;
}
🔹 If ptr points to arr[0], after ptr++, it points to arr[1].

2. Decrement (ptr--)
Decrementing a pointer moves it backward in memory.

#include <stdio.h>
int main()
{
int arr[] = {10, 20, 30};
int *ptr = &arr[2];
printf("Address before decrement: %p\n", ptr);
ptr--; // Moves one integer (4 bytes) backward
printf("Address after decrement: %p\n", ptr);

return 0;
}
🔹 If ptr points to arr[2], after ptr--, it points to arr[1].

3. Addition (ptr + n)
Adding an integer n moves the pointer forward by n elements.

#include <stdio.h>
int main()
{
int arr[] = {10, 20, 30, 40, 50};
int *ptr = arr;

printf("Value at ptr: %d\n", *ptr);


ptr = ptr + 2; // Moves 2 integers forward
printf("Value at ptr+2: %d\n", *ptr);

return 0;
}
🔹 Moves from arr[0] to arr[2] (20 ➝ 30).

4. Subtraction (ptr - n)
Subtracting an integer n moves the pointer backward by n elements.

#include <stdio.h>
int main()
{
int arr[] = {10, 20, 30, 40, 50};
int *ptr = &arr[3]; // Points to arr[3] (40)
printf("Value at ptr: %d\n", *ptr);
ptr = ptr - 2; // Moves 2 elements backward
printf("Value at ptr-2: %d\n", *ptr);
return 0;
}
🔹 Moves from arr[3] (40) to arr[1] (20).

Note:
❖ When a pointer (ptr) in C is moved below the 0th index or above the highest index of an array, it leads to
undefined behavior. This is because the pointer points to memory that is outside the allocated space
for the array, which can result in unpredictable results, crashes, or other issues.

Let's break it down:

1. Pointer Below the 0th Index (Accessing Memory Before the Array)

If you decrement the pointer such that it goes below the address of the first element of the array, the pointer is
essentially pointing to an invalid memory location. Dereferencing such a pointer (*ptr) can cause:
• Segmentation Fault: This can occur because you are trying to access memory that your program
doesn't have permission to access.
• Corruption of Data: Even if you don't crash, you may get unpredictable values since you're accessing
memory that is outside the array bounds.
In the given example, when you do:

ptr = ptr - 2; // Moves 2 elements backward


• ptr will point to memory before arr[0], which is undefined behavior and can cause your program to
malfunction.

2. Pointer Above the Last Index (Accessing Memory Beyond the Array)
Similarly, if you increment the pointer such that it goes beyond the last element of the array (in this case
beyond arr[4]), the pointer again points to an invalid location. Dereferencing the pointer here can also result in:
• Segmentation Fault: The program may crash because it’s trying to access memory that isn’t allocated
for the array.
• Garbage Data: Even if the program doesn't crash, you might read incorrect or garbage values from
memory that's not part of the array.
For example:
ptr = ptr + 2; // Moves 2 elements forward
This will move the pointer beyond arr[4] (which is the last element, 50), pointing to memory that is out of
bounds.

Why Undefined Behavior?


In C, the language doesn't have built-in bounds checking for arrays. This means that if you manipulate pointers
directly, there is no automatic protection to ensure that the pointer stays within valid bounds. This can lead to
memory access violations, crashes, or data corruption.

Best Practice:
To prevent such issues, always ensure that pointer arithmetic stays within the valid bounds of the array. For
example:
• When moving the pointer backward, ensure that it does not go below the base address of the array.
• When moving the pointer forward, ensure that it does not go beyond the last element of the array.

Example Modification to Avoid Out-of-Bounds Access:

#include <stdio.h>
int main()
{
int arr[] = {10, 20, 30, 40, 50};
int *ptr = &arr[3]; // Points to arr[3] (40)
printf("Value at ptr: %d\n", *ptr);

if (ptr - 2 >= arr)


{ // Check if moving backward is still within bounds
ptr = ptr - 2; // Moves 2 elements backward
printf("Value at ptr-2: %d\n", *ptr);
}
else
{
printf("Pointer moved below 0th index.\n");
}

if (ptr + 2 < arr + 5)


{ // Check if moving forward is still within bounds
ptr = ptr + 2; // Moves 2 elements forward
printf("Value at ptr+2: %d\n", *ptr);
}
Else
{
printf("Pointer moved above 4th index.\n");
}
return 0;
}
In this example:
• We ensure that ptr doesn't go below the 0th index or beyond the 4th index before performing pointer
arithmetic.

5. Pointer Subtraction (ptr1 - ptr2)


You can find the distance between two pointers of the same array.

#include <stdio.h>
int main()
{
int arr[] = {10, 20, 30, 40, 50};
int *ptr1 = &arr[4];
int *ptr2 = &arr[1];

printf("Difference: %ld\n", ptr1 - ptr2);


return 0;
}
🔹 Outputs 3, meaning there are 3 elements between ptr1 and ptr2.

6. Pointer Comparison (ptr1 > ptr2, ptr1 == ptr2)


Pointers can be compared to check their position in memory.

#include <stdio.h>
int main()
{
int arr[] = {10, 20, 30};
int *ptr1 = &arr[0], *ptr2 = &arr[2];

if (ptr1 < ptr2)


printf("ptr1 points to a lower memory address than ptr2\n");

return 0;
}
🔹 If ptr1 points to arr[0] and ptr2 to arr[2], ptr1 < ptr2 is true.

Pointer Arithmetic with Different Data Types


1. Integer Pointer (int *)
Moves by sizeof(int) (usually 4 bytes).
int *ptr;
ptr++; // Moves 4 bytes forward

2. Character Pointer (char *)


Moves by sizeof(char) (1 byte).
char *ptr;
ptr++; // Moves 1 byte forward

3. Float Pointer (float *)


Moves by sizeof(float) (4 bytes).
float *ptr;
ptr++; // Moves 4 bytes forward

4. Double Pointer (double *)


Moves by sizeof(double) (8 bytes).
double *ptr;
ptr++; // Moves 8 bytes forward

Key Takeaways
✔ Pointer arithmetic depends on the data type size.
✔ ptr++ moves forward by sizeof(type), ptr-- moves backward.
✔ ptr1 - ptr2 gives the number of elements between them.
✔ Pointer arithmetic is useful for arrays, strings, and dynamic memory handling.

Problems:
Beginner Level
1. Accessing Array Elements Using Pointers
Write a C program that declares an array of integers and uses pointer arithmetic to print all elements of
the array.

Example Output:
Enter 5 elements: 10 20 30 40 50
Elements are: 10 20 30 40 50

2. Find Sum Using Pointer Arithmetic


Write a function to calculate the sum of all elements in an array using pointers.
Function Prototype:
int sum(int *arr, int size);
Example:
int arr[] = {1, 2, 3, 4, 5};
printf("Sum: %d", sum(arr, 5));

Output:
Sum: 15

3. Reverse an Array Using Pointers


Write a program that reverses an array using only pointer operations.
Example Input:
12345
Output:
54321

Intermediate Level
4. Find Maximum Element in an Array Using Pointers
Write a function that returns the maximum element from an array using pointer arithmetic.
Function Prototype:
int findMax(int *arr, int size);

5. String Length Using Pointer Arithmetic


Implement your own version of strlen() using pointer arithmetic.
Function Prototype:
int my_strlen(char *str);
Example:
char str[] = "Hello";
printf("Length: %d", my_strlen(str));
Output:
Length: 5

6. Swapping Two Variables Using Pointers


Write a function that swaps two numbers using pointer arithmetic (without using temp variable).
Function Prototype:
void swap(int *a, int *b);

Advanced Level
7. Pointer-Based Matrix Addition
Write a program that takes two 3×3 matrices as input and adds them using pointer arithmetic.
8. Dynamic Memory Allocation & Pointer Arithmetic
Write a program that dynamically allocates an array of n integers, takes input, and prints the sum using
pointers.
9. Sorting an Array Using Pointer Arithmetic
Implement Bubble Sort or Selection Sort using only pointer arithmetic (no arr[i] indexing).
10. Find Unique Elements in an Array
Given an array of integers where every number appears twice except one, find the unique element using
pointer operations.

Pointers and Arrays in C


In C programming, pointers and arrays are closely related. Both are used to handle memory, but they serve
different purposes. Pointers are used to store memory addresses, and arrays are used to store a collection of
elements. Understanding how they work together is crucial in embedded systems and low-level programming,
where memory management is a key concern.

1. Array Name as a Pointer


In C, the name of an array represents the address of the first element of the array. This means that the array
name can be used as a pointer to access the array's elements.

Example:
#include <stdio.h>
int main()
{
int arr[] = {10, 20, 30, 40, 50};
int *ptr = arr; // Equivalent to &arr[0]

printf("First element: %d\n", *ptr); // Dereferencing the pointer


return 0;
}
Output:
First element: 10

In this example:
• arr is a pointer to the first element of the array.
• *ptr dereferences the pointer to access the first element of the array.

2. Accessing Array Elements Using Pointer Arithmetic


You can access array elements using pointer arithmetic. Since arrays are stored contiguously in memory,
pointers can be used to traverse the array.
Example:

#include <stdio.h>
int main()
{
int arr[] = {10, 20, 30, 40, 50};
int *ptr = arr;

for (int i = 0; i < 5; i++) {


printf("Element %d: %d\n", i + 1, *(ptr + i)); // Accessing using pointer arithmetic
}
return 0;
}

Output:
Element 1: 10
Element 2: 20
Element 3: 30
Element 4: 40
Element 5: 50

In this example:
• *(ptr + i) is used to access the i-th element of the array. This is equivalent to arr[i], but here we use the
pointer ptr to access the elements.

3. Pointer to Array
A pointer can store the address of an entire array. This is useful when you need to pass an array to a function,
especially if the size of the array is fixed and known.
Example:

#include <stdio.h>
void printArray(int (*ptr)[5])
{
for (int i = 0; i < 5; i++)
{
printf("%d ", (*ptr)[i]);
}
printf("\n");
}

int main()
{
int arr[] = {10, 20, 30, 40, 50};
int (*ptr)[5] = &arr;
// Pointer to the whole array
printArray(ptr);
return 0;
}
Output:
10 20 30 40 50

In this example:
• int (*ptr)[5] declares ptr as a pointer to an array of 5 integers.
• We pass ptr to the printArray function to print all the elements of the array.

4. Array of Pointers
An array of pointers is an array where each element is a pointer. This is useful when you want to create an array
of strings, or when each pointer in the array points to a different location.
Example1:

#include <stdio.h>
int main()
{
int a = 10, b = 20, c = 30;
int *arr[3]; // Array of pointers

arr[0] = &a;
arr[1] = &b;
arr[2] = &c;

for (int i = 0; i < 3; i++)


{
printf("Value at arr[%d]: %d\n", i, *arr[i]);
}
return 0;
}

Output:
Value at arr[0]: 10
Value at arr[1]: 20
Value at arr[2]: 30

In this example:
• arr is an array of 3 pointers to integers.
• We store the addresses of a, b, and c in arr[0], arr[1], and arr[2] respectively.
• Dereferencing arr[i] gives us the values of a, b, and c.

Example2:

#include <stdio.h>
int main()
{
char *names[] = {"Alice", "Bob", "Charlie"};
for (int i = 0; i < 3; i++)
{
printf("%s\n", names[i]); // Accessing using array of pointers
}
return 0;
}

Output:
Alice
Bob
Charlie

In this example:
• char *names[] is an array of pointers to strings.
• Each element stores the address of a string.

Summary of Key Concepts:


1. Array Name as a Pointer:
o The name of an array is a pointer to its first element.
o Example: arr is equivalent to &arr[0].
2. Accessing Array Elements Using Pointer Arithmetic:
o Array elements can be accessed using pointers and pointer arithmetic.
o Example: *(arr + i) accesses the i-th element of the array.
3. Pointer to Array:
o A pointer can point to an entire array, not just a single element.
o Example: int (*ptr)[5] is a pointer to an array of 5 integers.
4. Array of Pointers:
o An array of pointers allows each element to point to a different memory location.
o Example: int *arr[3] is an array of 3 pointers to integers.

Practice Problems:
Here are some practice problems to strengthen your understanding of pointers and arrays in C:
1. Array and Pointer Basics:
o Create an array of 5 integers. Use pointers to print the values of each element in the array.
o Modify the elements of the array using pointer arithmetic.
2. Pointer to Array:
o Write a function that accepts a pointer to an array of 5 integers and returns the sum of the array
elements.
3. Array of Pointers:
o Create an array of strings (array of pointers to char). Write a function that takes the array and
prints each string in reverse order.
4. Pointer Arithmetic:
o Implement a function that takes an array and an integer n, and returns the n-th element using
pointer arithmetic.
5. Pointer and Array Memory:
o Demonstrate the difference between using array indexing (arr[i]) and pointer arithmetic (*(arr +
i)) by printing the elements of an array using both methods.

Practice Problems
Beginner Level
1. Print Array Elements Using Pointer Arithmetic
Write a program that takes an integer array as input and prints all elements using a pointer.
2. Find Maximum in an Array Using Pointers
Implement a function to find the maximum value in an array using pointer arithmetic.
3. Swap Two Elements in an Array Using Pointers
Write a function that swaps two elements in an array using pointers.

Intermediate Level
4. Reverse an Array Using Pointers
Implement a function to reverse an array in place using pointers.
5. Find Length of a String Without strlen()
Write a function to find the length of a string using pointer arithmetic.
6. Sort an Array Using Pointer Arithmetic
Implement Bubble Sort using only pointers (no indexing).

Advanced Level
7. Pointer to an Array - Matrix Operations
Write a program to perform addition of two 3x3 matrices using pointer-to-array notation.
8. Dynamic Memory Allocation & Pointer Arithmetic
Allocate memory dynamically for an array, take input, and print the sum of all elements using pointer
arithmetic.
9. Implement strcpy() Using Pointers
Write your own version of strcpy() using pointer arithmetic.
10. Find Unique Element in an Array
Given an array where every element appears twice except one, find the unique element using pointers.

Pointers and Strings in C:


Pointers and strings are closely related in C, as strings are essentially arrays of characters. A string is
represented as an array of characters with a null terminator ('\0') marking the end of the string. Pointers can be
used to manipulate strings efficiently.

1. String as a Pointer
In C, strings are stored as arrays of characters, and the array name itself is a pointer to the first element. A
string literal in C is stored as a pointer to a character array. The string itself is stored in a read-only memory
section.
Code:

#include <stdio.h>
int main()
{
char *str = "Hello, World!";
printf("String: %s\n", str); // Prints the entire string
return 0;
}
Output:
String: Hello, World!
• Explanation: str is a pointer to the first character of the string literal "Hello, World!". When printing str,
it prints the entire string as the pointer is pointing to the first character. String literals ("Hello") are read-
only, modifying them causes undefined behavior.

2. Pointer Iteration over String


You can use pointer arithmetic to iterate over a string by incrementing the pointer to move through each
character until the null terminator is encountered.
Code:

#include <stdio.h>
int main()
{
char *str = "Hello, World!";
while (*str)
{ // Iterate until the null terminator is encountered
printf("%c ", *str); // Print the current character
str++; // Move to the next character
}
printf("\n");
return 0;
}

Output:
Hello, World!

• Explanation: The pointer str starts at the first character of the string. The while loop iterates through
each character by incrementing the pointer (str++) until it reaches the null terminator ('\0').

3. String Modification Using Pointers


You can modify a string through a pointer by dereferencing it and changing the value at the pointed address.

Code:

#include <stdio.h>
int main()
{
char str[] = "Hello, World!";
char *ptr = str; // Pointer pointing to the start of the string

// Modify the second character


*(ptr + 1) = 'a';
printf("Modified string: %s\n", str);
return 0;
}
Output:
Modified string: Hallo, World!

• Explanation: The pointer ptr points to the first character of the string str. By using pointer arithmetic
*(ptr + 1), we access the second character ('e') and modify it to 'a', changing the string to "Hallo,
World!". This works only for modifiable character arrays, not string literals (char *str = "Hello";).

4. String as Array of Characters


You can also manipulate strings using an array of characters. Here, the array name acts as a pointer to the first
element.
Code:

#include <stdio.h>
int main()
{
char str[] = "Hello";
char *ptr = str; // Pointer to the first element of the array

printf("First character: %c\n", *ptr); // Access first character


ptr++; // Move pointer to the second character
printf("Second character: %c\n", *ptr);

return 0;
}
Output:

First character: H
Second character: e

• Explanation: Here, ptr points to the first character of the array str. Moving the pointer (ptr++) allows you
to access subsequent characters of the string.

5. Pointer to Array of Characters


If you have a pointer to an array of characters, you can use it to access the entire array.
Code:

#include <stdio.h>
int main()
{
char str[] = "Hello";
char (*ptr)[6] = &str; // Pointer to the entire array

// Access the first character using pointer to array


printf("First character: %c\n", (*ptr)[0]);
return 0;
}
Output:
First character: H

• Explanation: The pointer ptr points to the entire array str. By dereferencing it ((*ptr)[0]), we access the
first element of the array, which is 'H'.

Problems:
1. Copying Strings Using Pointers
We can copy one string to another using pointers.

#include <stdio.h>
void my_strcpy(char *dest, const char *src)
{
while (*src)
{
*dest = *src;
src++;
dest++;
}
*dest = '\0'; // Add null terminator
}

int main()
{
char source[] = "Pointers";
char destination[20];

my_strcpy(destination, source);
printf("Copied String: %s\n", destination);

return 0;
}
Output:
Copied String: Pointers

Key Takeaways:
• *dest = *src; copies character-by-character.
• We stop when *src == '\0'.

2. String Length Using Pointer Arithmetic


We can find the length of a string without using strlen().

#include <stdio.h>
int my_strlen(const char *str)
{
const char *ptr = str;
while (*ptr)
{
ptr++;
}
return ptr - str; // Length is the difference
}

int main()
{
char str[] = "Embedded Systems";
printf("Length: %d\n", my_strlen(str));

return 0;
}

Output:
Length: 17

Key Takeaways:
• ptr - str gives the length of the string.
• Efficient pointer arithmetic replaces strlen().

6. Reversing a String Using Pointers


We can reverse a string in place using two pointers.

#include <stdio.h>
#include <string.h>
void reverse_string(char *str)
{
char *start = str;
char *end = str + strlen(str) - 1;

while (start < end)


{
char temp = *start;
*start = *end;
*end = temp;
start++;
end--;
}
}

int main() {
char str[] = "Pointers";
reverse_string(str);
printf("Reversed: %s\n", str);

return 0;
}
Output:
Reversed: sretniop

Summary of Key Concepts:


• String as a Pointer: A string can be treated as a pointer to its first character. You can print or
manipulate strings using pointers.
• Pointer Iteration over String: Use pointer arithmetic to iterate over each character in a string.
• String Modification Using Pointers: Modify a string through a pointer by dereferencing and changing
the value at the pointed location.
• String as Array of Characters: A string can be an array of characters, and pointer arithmetic can be
used to access and modify individual characters.
• Pointer to Array of Characters: You can have a pointer to the entire string array and access characters
through it.

Practice Problems
Beginner Level
1. Print Each Character Using Pointer Arithmetic
Write a program to print each character of a string using pointer iteration.
2. Find String Length Without Using strlen()
Implement a function to find the length of a string using pointer arithmetic.
3. Concatenate Two Strings Using Pointers
Write a function that appends one string to another using pointers.

Intermediate Level
4. Reverse a String Using Pointers
Implement a function to reverse a string in place.
5. Copy a String Using Pointer Arithmetic
Implement your own version of strcpy().
6. Count Vowels in a String Using Pointers
Write a function to count the number of vowels (a, e, i, o, u) in a given string.

Advanced Level
7. Check If a String Is a Palindrome
Write a function to check if a string is a palindrome using two-pointer approach.
8. Tokenizing a String Using Pointers (strtok Implementation)
Write your own version of strtok() to split a string by spaces.
9. Find the First Non-Repeating Character in a String
Implement a function to find the first unique character in a string using pointer traversal.
10. Convert Lowercase to Uppercase Using Pointers
Write a function that converts a lowercase string to uppercase using pointer arithmetic.

Pointers and Functions in C


Pointers and functions in C allow you to pass values efficiently and manipulate data at the memory level.
Understanding how to pass pointers to functions and return pointers from functions is important for tasks like
dynamic memory allocation, modifying function arguments, and managing resources in embedded systems
programming.

1. Passing Pointer to Function


When you pass a pointer to a function, the function can modify the data at the address that the pointer points
to. This allows you to modify the original variable from within the function.
Code:
#include <stdio.h>
void changeValue(int *ptr)
{
*ptr = 10; // Dereference the pointer to change the value at the address
}

int main()
{
int num = 5;
printf("Before change: %d\n", num);
changeValue(&num); // Pass the address of num
printf("After change: %d\n", num);
return 0;
}
Output:
Before change: 5
After change: 10
• Explanation: The function changeValue takes a pointer to an integer as an argument. The original
variable num is passed by reference, allowing the function to modify it directly.

2. Returning Pointer from Function


A function can return a pointer, typically a pointer to a dynamically allocated memory or using static keyword,
allowing the calling code to work with that memory.
Code:

#include <stdio.h>
#include <stdlib.h>

int* createArray(int size)


{
int *arr = (int*)malloc(size * sizeof(int)); // Dynamically allocate memory
for (int i = 0; i < size; i++)
{
arr[i] = i + 1; // Initialize array
}
return arr; // Return pointer to the array
}

int main()
{
int size = 5;
int *arr = createArray(size);

printf("Array elements: ");


for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
free(arr); // Free the allocated memory
return 0;
}
Output:

Array elements: 1 2 3 4 5

• Explanation: The function createArray returns a pointer to a dynamically allocated array. The malloc
function is used to allocate memory for the array, and the function returns a pointer to that memory.

3. Function Pointer
A function pointer is a pointer that points to a function instead of a data value. You can use function pointers to
implement callback functions or dynamic dispatch in embedded systems.
Code:

#include <stdio.h>
void printMessage()
{
printf("Hello from the function pointer!\n");
}

int main()
{
void (*funcPtr)() = printMessage; // Function pointer initialization
funcPtr(); // Calling the function using the pointer
return 0;
}
Output:
Hello from the function pointer!

• Explanation: A function pointer funcPtr is declared to point to a function that takes no arguments and
returns nothing. The pointer is assigned the address of printMessage, and then the function is called
using funcPtr().

4. Array of Function Pointers


An array of function pointers can be used to store multiple functions, and it is useful when you need to call
different functions dynamically based on some condition.
Code:
#include <stdio.h>
void add()
{
printf("Add ition function\n");
}

void subtract()
{
printf("Subtraction function\n");
}

int main()
{
void (*funcPtr[2])() = { add, subtract }; // Array of function pointers

// Calling functions using function pointers


funcPtr[0](); // Calls add()
funcPtr[1](); // Calls subtract()

return 0;
}
Output:
Addition function
Subtraction function

• Explanation: An array of function pointers funcPtr stores addresses of functions add and subtract. The
functions can be called using the array elements funcPtr[0]() and funcPtr[1]().

5. Pointer to Function with Arguments


You can also use function pointers to point to functions that take arguments. Here’s an example of a function
pointer that takes an argument and returns a result.
Code:

#include <stdio.h>
int add(int a, int b)
{
return a + b;
}

int subtract(int a, int b)


{
return a - b;
}

int main()
{
int (*funcPtr)(int, int); // Function pointer that takes two integers and returns an integer

// Point to the add function and call it


funcPtr = add;
printf("Addition: %d\n", funcPtr(3, 4));

// Point to the subtract function and call it


funcPtr = subtract;
printf("Subtraction: %d\n", funcPtr(7, 5));

return 0;
}
Output:
Addition: 7
Subtraction: 2

• Explanation: The function pointer funcPtr is used to point to different functions (add and subtract). It
allows you to call the function with arguments dynamically.

Summary of Key Concepts:


• Passing Pointer to Function: Enables modification of the original variable.
• Returning Pointer from Function: Allows returning dynamically allocated memory from a function.
• Function Pointer: A pointer to a function, useful for callbacks and dynamic function calls.
• Array of Function Pointers: Stores multiple function pointers, useful in selecting and calling different
functions dynamically.
• Pointer to Function with Arguments: Enables passing arguments to functions via pointers, making
function calls more flexible.

Why Are Pointers and Functions Important in Embedded Systems?


• Efficiency: Pointers allow passing large data structures like arrays or structures without copying them,
making the code more efficient.
• Dynamic Memory: Returning pointers to dynamically allocated memory allows flexibility in managing
memory, particularly useful in resource-constrained embedded systems.
• Callback Functions: Function pointers are useful in implementing callbacks and event-driven
programming in embedded systems.

Practice Problems
Beginner Level
1. Modify Value Using Pointer to Function
Write a program that takes an integer as input, passes it to a function using a pointer, and modifies its
value inside the function.
2. Return Pointer from Function
Write a function that dynamically allocates memory for an array of integers, initializes it with values,
and returns the pointer to the array.
3. Simple Function Pointer Example
Write a program where a function pointer is used to call a function that calculates the area of a circle,
square, or rectangle, based on user input.

Intermediate Level
4. Array of Function Pointers for Basic Calculator
Implement a simple calculator using an array of function pointers for addition, subtraction,
multiplication, and division.
5. Function Pointer to Print Reverse String
Create a function pointer that calls a function to print a string in reverse order.
6. Function Pointer for Menu System
Implement a menu system using an array of function pointers to allow the user to choose between
multiple tasks (like calculating area, volume, etc.).

Advanced Level
7. Sorting Array Using Function Pointer
Write a function that sorts an array using function pointers for comparison, such as implementing
selection sort, bubble sort, etc.
8. Callback Function
Implement a callback function using a function pointer. Create a function that accepts another
function as an argument and calls it to perform a specific task.
9. Dynamic Function Call
Write a program that reads user input (a number) and calls a function from a set of functions based on
the input, using function pointers.
10. Function Pointer Array for Operations on Structures
Create an array of function pointers to operate on a structure (e.g., calculating area or perimeter for
different shapes).

Advanced Pointer Concepts in C


1. Void Pointer
A void pointer is a generic pointer that can store the address of any data type. It's often used for dynamic
memory management or function arguments when the data type is not known in advance.
Example:
#include <stdio.h>
void printValue(void *ptr, char type)
{
if (type == 'i') {
printf("Integer value: %d\n", *((int*)ptr));
} else if (type == 'f') {
printf("Float value: %.2f\n", *((float*)ptr));
}
}

int main() {
int num = 10;
float pi = 3.14;

printValue(&num, 'i'); // Pass integer pointer


printValue(&pi, 'f'); // Pass float pointer

return 0;
}
Output:
Integer value: 10
Float value: 3.14

Key Takeaways:
• A void pointer (void *ptr) can store the address of any data type.
• We cast the void * to the appropriate type before dereferencing it.

2. Dangling Pointer
A dangling pointer occurs when a pointer continues to hold the address of a memory location that has been
freed or deleted. Accessing such pointers can cause undefined behavior.
Example:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *ptr = (int*)malloc(sizeof(int)); // Dynamically allocate memory
*ptr = 50;

printf("Before free: %d\n", *ptr);

free(ptr); // Free the allocated memory


// ptr is now a dangling pointer
/ / Uncommenting the following line would result in undefined behavior
// printf("After free: %d\n", *ptr); // Accessing dangling pointer

return 0;
}
Key Takeaways:
• After calling free(), the pointer becomes dangling and should not be dereferenced.
• Best practice: Set the pointer to NULL after freeing the memory (ptr = NULL;).

3. Wild Pointer
A wild pointer is an uninitialized pointer that points to an unknown memory location. Dereferencing such
pointers can lead to undefined behavior.
Example:

#include <stdio.h>
int main()
{
int *ptr; // Uninitialized pointer

// Dereferencing wild pointer leads to undefined behavior


// printf("Value: %d\n", *ptr); // Uncommenting this line will cause a runtime error

return 0;
}
Key Takeaways:
• A wild pointer is an uninitialized pointer, and dereferencing it can cause a crash or unpredictable
behavior.
• Always initialize pointers (e.g., int *ptr = NULL; or point to a valid memory).

4. Constant Pointer (int *const ptr)


A constant pointer is a pointer whose address cannot be changed after initialization, but the data pointed to
can be modified.
Example:

#include <stdio.h>
int main()
{
int a = 5, b = 10;
int *const ptr = &a; // Constant pointer, points to 'a' and cannot be changed

*ptr = 20; // Allowed, modifying the data pointed by ptr


// ptr = &b; // Not allowed, changing the pointer address is not allowed
printf("Value of a: %d\n", a); // Output will be 20
return 0;
}

Key Takeaways:
• A constant pointer cannot point to a different memory location once initialized.
• However, the data that the pointer points to can be modified.

5. Pointer to Constant (const int *ptr)


A pointer to constant is a pointer that can point to different memory locations, but the data being pointed to
cannot be modified through that pointer.
Example:

#include <stdio.h>
int main()
{
int a = 5, b = 10;
const int *ptr = &a; // Pointer to constant, cannot modify the data

// *ptr = 20; // Not allowed, modifying the data is not allowed

printf("Value of a: %d\n", *ptr); // Prints value of a, which is 5

ptr = &b; // Allowed, can point to a different memory location


printf("Value of b: %d\n", *ptr); // Prints value of b, which is 10

return 0;
}

Key Takeaways:
• A pointer to constant cannot modify the data it points to.
• The pointer itself can be modified to point to another address.

6. Constant Pointer to Constant (const int *const ptr)


A constant pointer to constant is a pointer that cannot be modified in any way — neither the address it holds
nor the data it points to.
Example:

#include <stdio.h>
int main()
{
int a = 5, b = 10;
const int *const ptr = &a; // Constant pointer to constant data

// *ptr = 20; // Not allowed, cannot modify the data


// ptr = &b; // Not allowed, cannot change the address

printf("Value of a: %d\n", *ptr); // Prints value of a, which is 5

return 0;
}

Key Takeaways:
• A constant pointer to constant cannot be used to change the address or the data it points to.

Practice Problems
Beginner Level
1. Using Void Pointer
Write a function that takes a void * pointer and a type (int or float) to print the value of the variable it
points to.
2. Dangling Pointer
Write a program that demonstrates a dangling pointer by allocating memory, freeing it, and then trying
to access the freed memory.
Intermediate Level
3. Wild Pointer Initialization
Write a program that initializes a wild pointer and shows how dereferencing it can cause undefined
behavior.
4. Constant Pointer
Implement a program that demonstrates the usage of a constant pointer, where the pointer cannot
change the memory address, but the data can be modified.
5. Pointer to Constant
Write a program that demonstrates a pointer to constant, where the data cannot be modified through
the pointer, but the pointer can point to different addresses.
Advanced Level
6. Constant Pointer to Constant
Write a program that demonstrates a constant pointer to constant, where neither the address nor the
data can be changed.
7. Memory Management and Dangling Pointers
Create a program where you allocate memory dynamically, use the pointer, and then free it. Later,
attempt to use the pointer without setting it to NULL to show a dangling pointer issue.
Pointers and Structures
Pointers and structures are frequently used together in advanced data structures such as linked lists, trees,
and other dynamic memory allocation scenarios. Using pointers with structures allows efficient memory usage
and manipulation of complex data types.
1. Pointer to Structure
A pointer to a structure is used to access members of the structure indirectly through the pointer. This is
helpful in cases where the structure is dynamically allocated (e.g., using malloc) or when passing a structure to
a function by reference.
Example:
#include <stdio.h>
struct Student
{
int id;
char name[50];
};

int main() {
struct Student student1 = {1, "John Doe"};
struct Student *ptr = &student1; // Pointer to the structure

printf("Student ID: %d\n", ptr->id); // Accessing member using pointer


printf("Student Name: %s\n", ptr->name);

return 0;
}
Output:
Student ID: 1
Student Name: John Doe

Key Takeaways:
• A pointer to a structure holds the memory address of a structure.
• You can use -> to access the members of the structure when using a pointer.

2. Accessing Members using Arrow (->)


The arrow operator (->) is a shortcut to access members of a structure through a pointer. It is equivalent to
(*ptr).member.
Example:

#include <stdio.h>
struct Student
{
int id;
char name[50];
};

int main() {
struct Student student1 = {2, "Jane Smith"};
struct Student *ptr = &student1;

// Accessing members using arrow operator


ptr->id = 100; // Same as (*ptr).id = 100;
printf("Updated Student ID: %d\n", ptr->id);

return 0;
}
Output:
Updated Student ID: 100
Key Takeaways:
• The arrow operator (->) is used to access the members of a structure when you have a pointer to the
structure.
• This operator simplifies the syntax compared to using (*ptr).member.

3. Structure Containing a Pointer


A structure containing a pointer is a common pattern in dynamic memory allocation, where a structure holds
pointers to other structures, arrays, or dynamically allocated memory.
Example:

#include <stdio.h>
#include <stdlib.h>
struct Student
{
int *marks; // Pointer to dynamically allocated memory for marks
};

int main() {
struct Student student1;
student1.marks = (int*)malloc(3 * sizeof(int)); // Dynamically allocate memory for 3 marks

student1.marks[0] = 85;
student1.marks[1] = 90;
student1.marks[2] = 95;

printf("Marks: %d, %d, %d\n", student1.marks[0], student1.marks[1], student1.marks[2]);

free(student1.marks); // Free allocated memory


return 0;
}
Output:
Marks: 85, 90, 95
Key Takeaways:
• A structure containing a pointer can dynamically allocate memory or store the address of other
objects (e.g., arrays or other structures).
• The pointer can be dereferenced to access or modify the contents it points to.

4. Array of Structure Pointers


An array of structure pointers is an array where each element is a pointer to a structure. This is useful when
you have a collection of dynamically allocated structures, or when you want to manage a set of structures
using pointers.
Example:

#include <stdio.h>
struct Student
{
int id;
char name[50];
};

int main()
{
struct Student student1 = {1, "John"};
struct Student student2 = {2, "Alice"};
struct Student student3 = {3, "Bob"};
// Array of structure pointers
struct Student *arr[3] = {&student1, &student2, &student3};

for (int i = 0; i < 3; i++)


{
printf("Student ID: %d, Name: %s\n", arr[i]->id, arr[i]->name);
}
return 0;
}
Output:
Student ID: 1, Name: John
Student ID: 2, Name: Alice
Student ID: 3, Name: Bob
Key Takeaways:
• An array of structure pointers allows you to store multiple pointers to structures.
• This is useful in scenarios where you need to manage a collection of dynamically allocated structures
or a large number of structures.

Practice Problems
Beginner Level
1. Pointer to Structure
Write a program that defines a Person structure with name and age fields. Use a pointer to access and
print the values of these fields.
2. Using Arrow Operator
Write a program where you create a structure Book with title and author. Use the arrow operator to
access and display the fields via a pointer.
Intermediate Level
3. Structure Containing Pointer
Create a structure Student with a pointer to an array of integers representing marks. Dynamically
allocate memory for the marks and display them.
4. Array of Structure Pointers
Create a structure Employee with fields id, name, and salary. Create an array of structure pointers and
display the details of all employees.
Advanced Level
5. Linked List Using Structure and Pointer
Implement a singly linked list using structures and pointers. Create functions to insert, display, and
delete nodes in the linked list.
6. Dynamic Memory Allocation in Structure
Create a structure Matrix that contains a pointer to a 2D array (matrix). Dynamically allocate memory
for a matrix and fill it with values. Then, print the matrix.

You might also like