Practice essential pointer programs in C including swap using pointers, string operations with pointers, dynamic memory allocation, and pointer-based data manipulation.
The best way to solidify your understanding of pointers is through practice. This collection covers the most essential pointer-based programs — from basic operations like swapping values to more advanced topics like dynamic arrays and pointer-based string manipulation. These are frequently asked in technical interviews and university examinations.
Program 1: Swap Two Numbers Using Pointers
The classic pointer demonstration — modifying values through addresses:
#include <stdio.h>
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 25, y = 50;
printf("Before swap: x = %d, y = %d\n", x, y);
printf("Addresses: &x = %p, &y = %p\n", (void*)&x, (void*)&y);
swap(&x, &y);
printf("After swap: x = %d, y = %d\n", x, y);
return 0;
}
Before swap: x = 25, y = 50
Addresses: &x = 0x7ffd4a2c, &y = 0x7ffd4a28
After swap: x = 50, y = 25
Swap Process:
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ x = 25 │ │ y = 50 │ →→→ │ x = 50 │ │ y = 25 │
└─────────┘ └─────────┘ └─────────┘ └─────────┘
↑ ↑
a b (pointers inside swap function)
temp = *a (25)
*a = *b (x becomes 50)
*b = temp (y becomes 25)
Program 2: Reverse a String Using Pointers
#include <stdio.h>
#include <string.h>
void reverseString(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[] = "Hello World";
printf("Original: %s\n", str);
reverseString(str);
printf("Reversed: %s\n", str);
return 0;
}
Original: Hello World
Reversed: dlroW olleH
Program 3: String Copy Using Pointers
#include <stdio.h>
void stringCopy(char *dest, const char *src) {
while (*src != '\0') {
*dest = *src;
dest++;
src++;
}
*dest = '\0'; // Don't forget null terminator
}
// Compact version
void stringCopyCompact(char *dest, const char *src) {
while ((*dest++ = *src++) != '\0');
}
int main() {
char source[] = "Pointer Magic";
char destination[50];
stringCopy(destination, source);
printf("Source: %s\n", source);
printf("Copied: %s\n", destination);
return 0;
}
Source: Pointer Magic
Copied: Pointer Magic
Program 4: String Length Using Pointers
#include <stdio.h>
int stringLength(const char *str) {
const char *ptr = str;
while (*ptr != '\0') {
ptr++;
}
return ptr - str; // Pointer difference = character count
}
int main() {
char msg[] = "C Programming";
printf("\"%s\" has %d characters\n", msg, stringLength(msg));
char empty[] = "";
printf("\"%s\" has %d characters\n", empty, stringLength(empty));
return 0;
}
"C Programming" has 13 characters
"" has 0 characters
#include <stdio.h>
#include <stdlib.h>
int main() {
int n;
printf("How many numbers? ");
scanf("%d", &n);
// Dynamically allocate array
int *arr = (int *)malloc(n * sizeof(int));
if (arr == NULL) {
printf("Memory allocation failed!\n");
return 1;
}
// Input using pointer
printf("Enter %d numbers:\n", n);
for (int i = 0; i < n; i++) {
scanf("%d", arr + i); // arr + i = &arr[i]
}
// Find sum using pointer traversal
int sum = 0;
int *ptr = arr;
for (int i = 0; i < n; i++) {
sum += *ptr;
ptr++;
}
printf("Sum = %d\n", sum);
printf("Average = %.2f\n", (float)sum / n);
free(arr);
return 0;
}
How many numbers? 5
Enter 5 numbers:
10 20 30 40 50
Sum = 150
Average = 30.00
Program 6: Dynamic 2D Array (Matrix Operations)
#include <stdio.h>
#include <stdlib.h>
int** allocateMatrix(int rows, int cols) {
int **matrix = (int **)malloc(rows * sizeof(int *));
for (int i = 0; i < rows; i++) {
matrix[i] = (int *)calloc(cols, sizeof(int)); // Zero-initialized
}
return matrix;
}
void freeMatrix(int **matrix, int rows) {
for (int i = 0; i < rows; i++) free(matrix[i]);
free(matrix);
}
void printMatrix(int **matrix, int rows, int cols) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%4d", matrix[i][j]);
}
printf("\n");
}
}
int** multiplyMatrices(int **a, int **b, int r1, int c1, int c2) {
int **result = allocateMatrix(r1, c2);
for (int i = 0; i < r1; i++) {
for (int j = 0; j < c2; j++) {
for (int k = 0; k < c1; k++) {
result[i][j] += a[i][k] * b[k][j];
}
}
}
return result;
}
int main() {
int **a = allocateMatrix(2, 3);
int **b = allocateMatrix(3, 2);
// Fill matrix A
int valA[2][3] = {{1, 2, 3}, {4, 5, 6}};
for (int i = 0; i < 2; i++)
for (int j = 0; j < 3; j++)
a[i][j] = valA[i][j];
// Fill matrix B
int valB[3][2] = {{7, 8}, {9, 10}, {11, 12}};
for (int i = 0; i < 3; i++)
for (int j = 0; j < 2; j++)
b[i][j] = valB[i][j];
printf("Matrix A (2x3):\n");
printMatrix(a, 2, 3);
printf("\nMatrix B (3x2):\n");
printMatrix(b, 3, 2);
int **result = multiplyMatrices(a, b, 2, 3, 2);
printf("\nA × B (2x2):\n");
printMatrix(result, 2, 2);
freeMatrix(a, 2);
freeMatrix(b, 3);
freeMatrix(result, 2);
return 0;
}
Matrix A (2x3):
1 2 3
4 5 6
Matrix B (3x2):
7 8
9 10
11 12
A × B (2x2):
58 64
139 154
Program 7: Resizable Array (Dynamic Growth)
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int *data;
int size;
int capacity;
} DynamicArray;
DynamicArray* createDynArray(int initialCap) {
DynamicArray *da = (DynamicArray *)malloc(sizeof(DynamicArray));
da->data = (int *)malloc(initialCap * sizeof(int));
da->size = 0;
da->capacity = initialCap;
return da;
}
void push(DynamicArray *da, int value) {
if (da->size >= da->capacity) {
da->capacity *= 2;
da->data = (int *)realloc(da->data, da->capacity * sizeof(int));
printf(" [Resized to capacity %d]\n", da->capacity);
}
da->data[da->size++] = value;
}
void freeDynArray(DynamicArray *da) {
free(da->data);
free(da);
}
int main() {
DynamicArray *arr = createDynArray(4);
printf("Adding elements:\n");
for (int i = 1; i <= 10; i++) {
push(arr, i * 10);
printf(" Added %d (size=%d, capacity=%d)\n", i * 10, arr->size, arr->capacity);
}
printf("\nFinal array: ");
for (int i = 0; i < arr->size; i++) {
printf("%d ", arr->data[i]);
}
printf("\n");
freeDynArray(arr);
return 0;
}
Adding elements:
Added 10 (size=1, capacity=4)
Added 20 (size=2, capacity=4)
Added 30 (size=3, capacity=4)
Added 40 (size=4, capacity=4)
[Resized to capacity 8]
Added 50 (size=5, capacity=8)
Added 60 (size=6, capacity=8)
Added 70 (size=7, capacity=8)
Added 80 (size=8, capacity=8)
[Resized to capacity 16]
Added 90 (size=9, capacity=16)
Added 100 (size=10, capacity=16)
Final array: 10 20 30 40 50 60 70 80 90 100
Program 8: Find Duplicates Using Pointer to Array
#include <stdio.h>
#include <stdlib.h>
void findDuplicates(int *arr, int n) {
int *sorted = (int *)malloc(n * sizeof(int));
// Copy array
for (int i = 0; i < n; i++) {
*(sorted + i) = *(arr + i);
}
// Simple bubble sort on copy
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (*(sorted + j) > *(sorted + j + 1)) {
int temp = *(sorted + j);
*(sorted + j) = *(sorted + j + 1);
*(sorted + j + 1) = temp;
}
}
}
// Find duplicates in sorted array
printf("Duplicates: ");
int found = 0;
for (int i = 0; i < n - 1; i++) {
if (*(sorted + i) == *(sorted + i + 1)) {
if (i == 0 || *(sorted + i) != *(sorted + i - 1)) {
printf("%d ", *(sorted + i));
found = 1;
}
}
}
if (!found) printf("None");
printf("\n");
free(sorted);
}
int main() {
int arr[] = {4, 2, 7, 2, 4, 8, 7, 1};
int n = sizeof(arr) / sizeof(arr[0]);
printf("Array: ");
for (int i = 0; i < n; i++) printf("%d ", arr[i]);
printf("\n");
findDuplicates(arr, n);
return 0;
}
Array: 4 2 7 2 4 8 7 1
Duplicates: 2 4 7
Program 9: String Concatenation Using Pointers
#include <stdio.h>
void strConcat(char *dest, const char *src) {
// Move to end of dest
while (*dest != '\0') {
dest++;
}
// Copy src
while (*src != '\0') {
*dest = *src;
dest++;
src++;
}
*dest = '\0';
}
int main() {
char result[100] = "Hello";
strConcat(result, ", ");
strConcat(result, "World");
strConcat(result, "!");
printf("Result: %s\n", result);
return 0;
}
Program 10: Return Multiple Values via Pointers
#include <stdio.h>
void analyzeArray(const int *arr, int n, int *sum, float *avg, int *min, int *max) {
*sum = 0;
*min = *arr;
*max = *arr;
const int *ptr = arr;
for (int i = 0; i < n; i++) {
*sum += *ptr;
if (*ptr < *min) *min = *ptr;
if (*ptr > *max) *max = *ptr;
ptr++;
}
*avg = (float)(*sum) / n;
}
int main() {
int arr[] = {34, 78, 12, 56, 90, 23, 67, 45};
int n = sizeof(arr) / sizeof(arr[0]);
int sum, min, max;
float avg;
analyzeArray(arr, n, &sum, &avg, &min, &max);
printf("Array: ");
for (int i = 0; i < n; i++) printf("%d ", arr[i]);
printf("\n\nAnalysis:\n");
printf(" Sum: %d\n", sum);
printf(" Average: %.2f\n", avg);
printf(" Minimum: %d\n", min);
printf(" Maximum: %d\n", max);
return 0;
}
Array: 34 78 12 56 90 23 67 45
Analysis:
Sum: 405
Average: 50.62
Minimum: 12
Maximum: 90
Interview Questions
**Q1: What is the difference between int *p = &x and *p = x?**
int *p = &x is a declaration — it creates a pointer p and initializes it with the address of x. *p = x is an assignment — it writes the value of x into the memory location pointed to by p. The * means different things in declaration vs. expression context.
Q2: How do you dynamically allocate a 2D array and ensure memory is freed properly?
Allocate an array of row pointers (int **), then allocate each row separately. When freeing, free each row first (inner), then free the row pointer array (outer). Reversing this order causes a memory leak.
Q3: Why should you always check the return value of malloc?
malloc returns NULL when the system cannot allocate the requested memory. Dereferencing NULL causes a segmentation fault. Always check: if (ptr == NULL) { /* handle error */ }.
Q4: What is a memory leak and how do pointers cause them?
A memory leak occurs when dynamically allocated memory is never freed. If the only pointer to an allocated block is reassigned or goes out of scope without calling free, that memory becomes unreachable but remains allocated until the program exits.
Q5: How does realloc work and what happens to the original pointer?
realloc resizes a previously allocated block. If possible, it extends in place. Otherwise, it allocates a new block, copies data, and frees the old block. Always assign the result to a temporary pointer first — if realloc fails (returns NULL), the original pointer remains valid.
Summary
- Swapping values requires pointers because C uses pass-by-value for function arguments
- String operations with pointers use the pattern: traverse until
'\0', operate on *ptr - Dynamic arrays use
malloc/realloc and must be free'd to avoid memory leaks - Returning multiple values from a function requires passing output pointers
- Always check
malloc's return value and free memory in reverse allocation order - Pointer-based code is often more efficient than index-based code for sequential access