PYnative

Python Programming

  • Learn Python
    • Python Tutorials
    • Python Basics
    • Python Interview Q&As
  • Exercises
  • Quizzes
  • Code Editor
Home » C Programming Exercises » C Programming Pointers Exercises: Beginner to Advanced Mastery

C Programming Pointers Exercises: Beginner to Advanced Mastery

Updated on: December 10, 2025 | Leave a Comment

This guide provides 30 C programming exercises on pointers ranging from basic to advanced concepts.

Pointers are the single most powerful, yet often challenging, concept in C programming. They are essential for low-level memory management, efficient array and string manipulation, and implementing complex data structures.

Each exercise includes a Problem Statement, Hint, Solution code, and detailed Explanation, ensuring you don’t just copy code, but genuinely understand how and why it works.

What You’ll Practice

The exercises cover the following core topics:

  • Fundamentals: Mastering pointer declaration, dereferencing, and the address-of operator (&).
  • Data Structures: Working with Pointers with Strings and Arrays and implementing Double Pointers (Pointers to Pointers).
  • Memory Management: Practical use of Dynamic Memory Allocation (DMA) using malloc(), calloc(), and free().
  • Complex Scenarios: Applying pointers with Functions and Structs (e.g., passing by reference).
  • Advanced Topics: Exploring Pointer Arithmetic and other complex pointer concepts.

Use Online C Compiler to solve exercises.

+ Table Of Contents (30 Exercises)

Table of contents

  • Exercise 1: Declaration and Initialization
  • Exercise 2: Accessing Value (Dereferencing)
  • Exercise 3: Address Operator
  • Exercise 4: Pointer Size
  • Exercise 5: Passing by Reference
  • Exercise 6: Array Traversal
  • Exercise 7: Accessing Array Elements
  • Exercise 8: Pointers to an Array (Array Name as Pointer)
  • Exercise 9: Sum of Array Elements
  • Exercise 10: Reverse an Array
  • Exercise 11: String Length
  • Exercise 12: String Copy
  • Exercise 13: Vowel Counter
  • Exercise 14: Print Individual Characters
  • Exercise 15: Basic malloc
  • Exercise 16: Dynamic Array
  • Exercise 17: Using calloc
  • Exercise 18: Using realloc
  • Exercise 19: Memory Allocation Check
  • Exercise 20: Introduction to Double Pointers
  • Exercise 21: Function with Double Pointer
  • Exercise 22: 2D Array Simulation
  • Exercise 23: Swap Two Numbers
  • Exercise 24: Return Multiple Values
  • Exercise 25: Pointer to a Function (Function Pointers)
  • Exercise 26: Structure Pointer
  • Exercise 27: Array of Structures
  • Exercise 28: Dynamic Structure Allocation
  • Exercise 29: Generic Pointers ( void * )
  • Exercise 30: Pointer Arithmetic Boundary

Exercise 1: Declaration and Initialization

Problem Statement: Declare an integer variable, a pointer to an integer, and initialize the pointer to the address of the variable. Print both the variable’s value and the value accessed via the pointer.

Given:

int var = 42;Code language: C++ (cpp)

Expected Output:

Memory Address can vary according to the system.

Variable 'var' value: 42
Variable 'var' address: 0x7ffc170d9ffc
Pointer 'ptr' address (value of ptr): 0x7ffc170d9ffc
Value accessed via pointer (*ptr): 42
+ Hint

Use the address-of operator (&) to get the memory address of the variable and the dereference operator (*) to access the value stored at the pointer’s address.

+ Show Solution
#include <stdio.h>

int main() {
    int var = 42;             // Declare and initialize an integer variable
    int *ptr;                 // Declare a pointer to an integer

    ptr = &var;               // Initialize the pointer with the address of 'var'

    printf("Variable 'var' value: %d\n", var);
    printf("Variable 'var' address: %p\n", &var);
    printf("Pointer 'ptr' address (value of ptr): %p\n", ptr);
    printf("Value accessed via pointer (*ptr): %d\n", *ptr);

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • int var = 42; declares an integer var.
  • int *ptr; declares ptr as a pointer to an integer. The asterisk (*) signifies it’s a pointer type.
  • ptr = &var; assigns the memory address of var to ptr using the address-of operator (&).
  • *ptr uses the dereference operator to retrieve the value stored at the memory address currently held by ptr, which is 42.

Exercise 2: Accessing Value (Dereferencing)

Problem Statement: Write a program that uses the dereference operator (*) to change the value of a variable through its pointer.

Given:

int num = 100;Code language: C++ (cpp)

Expected Output:

Original value of num: 100
New value of num after pointer assignment: 500
+ Hint

First, make the pointer point to the variable. Then, use the dereference operator on the pointer on the left side of an assignment operation.

+ Show Solution
#include <stdio.h>

int main() {
    int num = 100;
    int *p_num = &num;

    printf("Original value of num: %d\n", num);

    // Change the value of 'num' using the pointer 'p_num'
    *p_num = 500;

    printf("New value of num after pointer assignment: %d\n", num);

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • The pointer p_num is initialized to hold the address of num.
  • The line *p_num = 500; is the key. The dereference operator (*) tells the compiler to go to the memory location stored in p_num and place the value 500 there.
  • Since p_num points to num, the value of num itself is updated from 100 to 500.

Exercise 3: Address Operator

Problem Statement: Print the memory addresses of two different variables (e.g., an int and a float) using the address-of operator (&). Additionally, print the address of a pointer variable itself.

Given:

int a = 10;
float b = 20.5f;Code language: C++ (cpp)

Expected Output:

Address of integer variable 'a': 0x7ffdd91e2bd8
Address of float variable 'b': 0x7ffdd91e2bdc
Address stored IN pointer 'p_a': 0x7ffdd91e2bd8
Address of pointer variable 'p_a' itself: 0x7ffdd91e2be0
+ Hint

Use the %p format specifier in printf() to print memory addresses. Every variable, including a pointer variable, has its own unique memory address.

+ Show Solution
#include <stdio.h>

int main() {
    int a = 10;
    float b = 20.5f;
    int *p_a = &a; // A pointer variable itself

    printf("Address of integer variable 'a': %p\n", &a);
    printf("Address of float variable 'b': %p\n", &b);
    printf("Address stored IN pointer 'p_a': %p\n", p_a);
    printf("Address of pointer variable 'p_a' itself: %p\n", &p_a);

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • The address-of operator (&) is used with &a and &b to retrieve the starting memory location of those variables.
  • The output shows that even a pointer variable (p_a) takes up space in memory and has its own unique address, retrieved by &p_a. The value stored inside p_a is the address of a.

Exercise 4: Pointer Size

Problem Statement: Write a program to print the size (in bytes) of a pointer to an integer, a pointer to a character, and a pointer to a float on your system.

Expected Output:

Size of int pointer (int *): 8 bytes
Size of char pointer (char *): 8 bytes
Size of float pointer (float *): 8 bytes

Size of 'int' variable: 4 bytes
Size of 'float' variable: 4 bytes
+ Hint

Use the sizeof() operator on the declared pointer variables or the pointer types themselves (e.g., sizeof(int *), sizeof(char *)).

+ Show Solution
#include <stdio.h>

int main() {
    int *int_ptr;
    char *char_ptr;
    float *float_ptr;

    printf("Size of int pointer (int *): %zu bytes\n", sizeof(int_ptr));
    printf("Size of char pointer (char *): %zu bytes\n", sizeof(char_ptr));
    printf("Size of float pointer (float *): %zu bytes\n", sizeof(float_ptr));
    printf("\n");
    printf("Size of 'int' variable: %zu bytes\n", sizeof(int));
    printf("Size of 'float' variable: %zu bytes\n", sizeof(float));

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

The size of a pointer (sizeof(type *)) is the same regardless of the data type it points to. This size (usually 4 or 8 bytes) is determined by the system’s architecture (e.g., 32-bit or 64-bit), as it needs to store a memory address.

  • The sizeof() operator returns a value of type size_t, which is printed using the %zu format specifier.
  • The size of the variable an integer pointer points to (sizeof(int)) is a completely separate value (e.g., 4 bytes).

Exercise 5: Passing by Reference

Problem Statement: Create a function increment_value that takes an integer pointer as an argument and increments the value of the variable it points to by one. Demonstrate the change in the main function.

Given:

int count = 10;Code language: C++ (cpp)

Expected Output:

Before function call, count = 10
After function call, count = 11
+ Hint

When calling the function, pass the address of the variable (&var). Inside the function, use the dereference operator (*) to access and modify the value at that address.

+ Show Solution
#include <stdio.h>

// Function takes a pointer to an integer
void increment_value(int *num_ptr) {
    // Access the value at the pointer's address and increment it
    (*num_ptr)++;
}

int main() {
    int count = 10;
    printf("Before function call, count = %d\n", count);

    // Pass the address of 'count' to the function (Pass by Reference)
    increment_value(&count);

    printf("After function call, count = %d\n", count);
    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • This exercise illustrates Pass by Reference (simulated in C using pointers). When increment_value(&count); is called, the address of count is passed, not its value.
  • Inside the function, num_ptr holds this address. The expression (*num_ptr)++ dereferences the pointer, accessing the original count variable, and then increments its value in memory.
  • This allows the function to permanently modify a variable defined outside its scope.

Exercise 6: Array Traversal

Problem Statement: Use pointer arithmetic to traverse an integer array and print all its elements.

Given:

int arr[] = {10, 20, 30, 40, 50};Code language: C++ (cpp)

Expected Output:

Array elements using pointer arithmetic:
Element 0: 10
Element 1: 20
Element 2: 30
Element 3: 40
Element 4: 50
+ Hint

Remember that the name of an array acts as a constant pointer to its first element. Start a pointer at the array’s base address and increment the pointer in the loop. The int pointer will automatically jump by sizeof(int) bytes.

+ Show Solution
#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30, 40, 50};
    int size = sizeof(arr) / sizeof(arr[0]);
    int *p = arr; // p now points to arr[0]

    printf("Array elements using pointer arithmetic:\n");

    for (int i = 0; i < size; i++) {
        printf("Element %d: %d\n", i, *(p + i));
        // Alternative: printf("Element %d: %d\n", i, *p); p++;
    }

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • int *p = arr; initializes the pointer p with the base address of the array (i.e., the address of arr[0]).
  • The expression (p + i) uses pointer arithmetic. Since p is an int *, adding i to it shifts the memory address by i×sizeof(int) bytes, correctly pointing to arr[i].
  • *(p + i) then dereferences this calculated address to retrieve the value of arr[i]. This is equivalent to arr[i].

Exercise 7: Accessing Array Elements

Problem Statement: Given an array, access and print the third element (index 2) using three different methods: subscript notation, pointer notation with the base address, and pointer notation with an offset pointer.

Given:

int data[5] = {1, 3, 5, 7, 9};Code language: C++ (cpp)

Expected Output:

Array element at index 2 (Value should be 5):
1. Subscript notation: 5
2. Pointer notation (arr + 2): 5
3. Pointer notation (ptr + 2): 5
+ Hint

The three equivalent notations are arr[i], *(arr + i), and *(ptr + i). Focus on index 2.

+ Show Solution
#include <stdio.h>

int main() {
    int data[5] = {1, 3, 5, 7, 9};
    int *ptr = data; // Pointer initialized to array base address

    printf("Array element at index 2 (Value should be 5):\n");

    // Method 1: Subscript notation (Standard Array access)
    printf("1. Subscript notation: %d\n", data[2]);

    // Method 2: Pointer notation with the base address (Array name as pointer)
    printf("2. Pointer notation (arr + 2): %d\n", *(data + 2));

    // Method 3: Pointer notation with the offset pointer
    printf("3. Pointer notation (ptr + 2): %d\n", *(ptr + 2));

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • In C, the expression arr[i] is internally converted by the compiler to *(arr + i). This highlights the fundamental relationship between arrays and pointers.
  • Method 1 (data[2]) is the standard, most readable way.
  • Method 2 (*(data + 2)) explicitly shows the pointer arithmetic. Since data is an alias for the base address, this works.
  • Method 3 (*(ptr + 2)) uses a separate pointer variable ptr that also holds the base address. All three expressions correctly resolve to the memory address of the third element.

Exercise 8: Pointers to an Array (Array Name as Pointer)

Problem Statement: Declare an array and attempt to assign a new address to the array’s name. Observe the compilation error and explain why it occurs.

Given:

int arr[5] = {1, 2, 3, 4, 5};
int other_var = 10;Code language: C++ (cpp)
+ Hint

The array name is a constant pointer to the first element’s address. You cannot change the address a constant pointer holds.

+ Show Solution
#include <stdio.h>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int other_var = 10;
    int *p = &other_var;

    printf("Address of arr[0]: %p\n", arr);
    printf("Address of other_var: %p\n", &other_var);

    // Compilation Error: Attempting to assign a new address to the array name
    // arr = p; // <--- UNCOMMENTING THIS LINE WILL CAUSE A COMPILATION ERROR!

    /* Correct way to use the array name for access */
    printf("Value of arr[2] using array name: %d\n", *(arr + 2));

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • The array name (arr) acts as a constant pointer (int *const) to its starting memory address. It always points to arr[0].
  • A constant pointer cannot have its stored address value changed after initialization.
  • If you uncomment arr = p;, the compiler will issue an error similar to: “assignment to expression with array type” or “lvalue required as left operand of assignment”. This error confirms that the array name itself is not a modifiable L-value (like a non-const pointer variable).

Exercise 9: Sum of Array Elements

Problem Statement: Write a function sum_array that accepts an integer pointer (the array base address) and the size of the array. The function must calculate and return the sum of all elements using pointer arithmetic for traversal.

Given:

int numbers[] = {10, 5, 8, 2, 15};Code language: C++ (cpp)

Expected Output:

The sum of array elements is: 40
+ Hint

Inside the function, use a loop and access elements using *(arr_ptr + i) or by incrementing the pointer itself, *arr_ptr++.

+ Show Solution
#include <stdio.h>

// Function takes the array base address and size
int sum_array(int *arr_ptr, int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        // Access the element using pointer arithmetic and dereference
        sum += *(arr_ptr + i);
    }
    return sum;
}

int main() {
    int numbers[] = {10, 5, 8, 2, 15};
    int size = 5;

    // Pass the array name (which is the base address)
    int total = sum_array(numbers, size);

    printf("The sum of array elements is: %d\n", total); // Output: 40

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • In the main function, the array name numbers is passed, which decays into a pointer (int *) to the first element.
  • The sum_array function receives this pointer as arr_ptr.
  • Inside the loop, *(arr_ptr + i) correctly retrieves the value of the i-th element by adding i to the base address and then dereferencing the resulting address. This is a common and efficient way to process arrays using pointers in C.

Exercise 10: Reverse an Array

Problem Statement: Write a program to reverse an integer array in place (without using a second array) by swapping elements using pointers.

Given:

int numbers[] = {1, 2, 3, 4, 5, 6};Code language: C++ (cpp)

Expected Output:

Original array: 1 2 3 4 5 6 
Reversed array: 6 5 4 3 2 1
+ Hint

Use two pointers: one starting at the beginning of the array and one at the end. In a loop, swap the values they point to and move the pointers towards the center until they cross or meet.

+ Show Solution
#include <stdio.h>

void print_array(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

void reverse_array(int *start, int *end) {
    while (start < end) {
        // Swap logic using a temporary variable
        int temp = *start;
        *start = *end;
        *end = temp;

        // Move pointers towards the middle
        start++;
        end--;
    }
}

int main() {
    int numbers[] = {1, 2, 3, 4, 5, 6};
    int size = 6;

    printf("Original array: ");
    print_array(numbers, size);

    // Pointers for the start and end of the array
    int *start_ptr = numbers;
    int *end_ptr = numbers + size - 1; // Address of the last element

    reverse_array(start_ptr, end_ptr);

    printf("Reversed array: ");
    print_array(numbers, size);

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • The reverse_array function takes two pointers: start (pointing to the first element) and end (pointing to the last).
  • The while (start < end) loop ensures the swapping continues only until the pointers cross, meaning all necessary pairs have been swapped.
  • Inside the loop, the line int temp = *start; retrieves the value at the start address.
  • *start = *end; overwrites the start value with the end value.
  • *end = temp; uses the stored original start value to complete the swap.
  • start++ and end-- use pointer arithmetic to move the pointers to the next respective element positions (the start pointer moves forward by sizeof(int), the end pointer moves backward).

Exercise 11: String Length

Problem Statement: Write a function custom_strlen to calculate the length of a string (null-terminated character array) without using the standard C library function strlen(). The function must use a character pointer to traverse the string until it finds the null terminator (\0).

Given:

char myString[] = "Hello Pointers!";Code language: C++ (cpp)

Expected Output:

The string is: "Hello Pointers!"
Length using custom_strlen: 15
+ Hint

Initialize a counter variable and a character pointer to the start of the string. In a while loop, check if the value pointed to by the pointer is not \0. If it’s not, increment both the counter and the pointer itself.

+ Show Solution
#include <stdio.h>

int custom_strlen(const char *s) {
    const char *p = s; // Start another pointer at the beginning
    int length = 0;

    // Loop until the pointer points to the null terminator ('\0')
    while (*p != '\0') {
        length++;
        p++; // Move the pointer to the next character address
    }
    return length;
}

int main() {
    char myString[] = "Hello Pointers!";
    int len = custom_strlen(myString);

    printf("The string is: \"%s\"\n", myString);
    printf("Length using custom_strlen: %d\n", len);

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • The function takes a const char *s (the string’s base address). Using const is good practice since we aren’t modifying the string.
  • A local pointer p is initialized to the start of the string.
  • The while (*p != '\0') condition is the core: it dereferences the pointer (*p) to check the value at the current address.
  • Inside the loop, p++ uses pointer arithmetic to move the pointer forward by sizeof(char) (1 byte), pointing to the next character. The loop counter length tracks the number of characters encountered.

Exercise 12: String Copy

Problem Statement: Implement a function custom_strcpy that copies the content of a source string (src) to a destination string (dest) using only character pointers.

Given:

char source[] = "Pointer Mastery";
char destination[50]; // Ensure destination buffer is large enoughCode language: C++ (cpp)

Expected Output:

Source: Pointer Mastery
Destination: Pointer Mastery
+ Hint

Use two pointers, one for the source and one for the destination. Loop until the null terminator is copied. You can do the assignment and pointer increment in a single, compact loop condition.

+ Show Solution
#include <stdio.h>

void custom_strcpy(char *dest, const char *src) {
    // Loop runs as long as the assignment is non-zero (i.e., not '\0')
    while (*src != '\0') {
        *dest = *src; // Copy the character
        dest++;       // Move dest pointer
        src++;        // Move src pointer
    }
    *dest = '\0'; // Crucially, terminate the destination string
}

int main() {
    char source[] = "Pointer Mastery";
    char destination[50]; // Ensure destination buffer is large enough

    custom_strcpy(destination, source);

    printf("Source: %s\n", source);
    printf("Destination: %s\n", destination);

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • The function takes two pointers: dest (modifiable) and src (read-only).
  • The loop iteratively copies the character value from the memory location pointed to by src into the location pointed to by dest.
  • Pointer increments (dest++ and src++) move both pointers to the next available memory location (1 byte forward).
  • The loop stops just before the null terminator is copied. Therefore, the line *dest = '\0'; is essential to properly terminate the destination string, making it a valid C string.

Exercise 13: Vowel Counter

Problem Statement: Count the number of vowels (A, E, I, O, U, and their lowercase counterparts) in a given string using a character pointer for traversal.

Given:

char sentence[] = "The quick brown fox Jumps over the lazy dog";Code language: C++ (cpp)

Expected Output:

Sentence: The quick brown fox Jumps over the lazy dog
Total number of vowels: 11
+ Hint

Use a loop that iterates through the string with a pointer. Inside the loop, check the dereferenced character against all 10 possible vowel cases. You might use tolower() or check both cases explicitly.

+ Show Solution
#include <stdio.h>

int count_vowels(const char *s) {
    int count = 0;
    const char *p = s;

    while (*p != '\0') {
        char c = *p;

        // Check if the current character is a vowel (case-insensitive)
        if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' ||
            c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U') {
            count++;
        }
        p++; // Move to the next character
    }
    return count;
}

int main() {
    char sentence[] = "The quick brown fox Jumps over the lazy dog";
    int vowels = count_vowels(sentence);

    printf("Sentence: %s\n", sentence);
    printf("Total number of vowels: %d\n", vowels); // Output: 11

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • The function uses a pointer p to iterate over the input string.
  • In each iteration, char c = *p; stores the current character.
  • The if condition explicitly checks for all 10 possible vowel characters (uppercase and lowercase).
  • The pointer p is incremented in every step (p++), efficiently moving to the next address until the null terminator is reached, ensuring all characters are processed.

Exercise 14: Print Individual Characters

Problem Statement: Use a pointer to iterate through a string and print each character on a new line, stopping at the null terminator.

Given:

 char *message = "C Pointers";Code language: C++ (cpp)

Expected Output:

Printing characters:
C

P
o
i
n
t
e
r
s
+ Hint

The string name is the pointer. You can use a for loop, initializing a pointer to the string’s base address, continuing as long as the dereferenced value is not \0, and using the increment operator (p++) in the loop’s update section.

+ Show Solution
#include <stdio.h>

int main() {
    char *message = "C Pointers";
    char *p;

    printf("Printing characters:\n");

    // Loop using the pointer
    for (p = message; *p != '\0'; p++) {
        printf("%c\n", *p);
    }

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • char *message = "C Pointers"; creates a character pointer that points to a string literal (usually stored in read-only memory).
  • The for loop initializes the local pointer p to point to the start of the string (message).
  • The condition *p != '\0' checks if the current character is the null terminator. The loop continues as long as it’s not.
  • The update p++ moves the pointer to the next character.
  • printf("%c\n", *p); prints the value of the character the pointer is currently pointing to, followed by a newline.

Exercise 15: Basic malloc

Problem Statement: Dynamically allocate memory for a single integer using malloc(). Store the value 108 in this allocated memory, print the value and its memory address, and then free the memory using free().

Expected Output:

Value stored dynamically: 108
Memory address allocated: 0x5696c3bc92a0
+ Hint

malloc() returns a void *, which must be cast to int *. Use sizeof(int) to specify the size required. Always check if malloc returns NULL.

+ Show Solution
#include <stdio.h>
#include <stdlib.h> // Required for malloc and free

int main() {
    int *ptr = NULL;

    // Allocate memory for one integer
    ptr = (int *)malloc(sizeof(int));

    // Check if allocation was successful
    if (ptr == NULL) {
        printf("Error: Memory allocation failed!\n");
        return 1;
    }

    // Store value using dereference
    *ptr = 108;

    printf("Value stored dynamically: %d\n", *ptr);
    printf("Memory address allocated: %p\n", (void *)ptr);

    // Release the dynamically allocated memory
    free(ptr);
    ptr = NULL; // Good practice to set pointer to NULL after freeing

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • malloc(sizeof(int)) requests enough memory to store one integer. It returns the starting address of the block.
  • This address is cast to (int *) and assigned to ptr.
  • if (ptr == NULL) is crucial for error checking; it ensures the program doesn’t try to access non-existent memory.
  • *ptr = 108; uses the pointer to write the value into the allocated space.
  • free(ptr); returns the block of memory back to the heap for future use, preventing a memory leak. Setting ptr = NULL afterwards avoids using a dangling pointer.

Exercise 16: Dynamic Array

Problem Statement: Dynamically allocate memory for an array of 5 integers using malloc(). Read 5 integer values from the user into the array, print them using pointer arithmetic, and finally, free the allocated memory.

Given:

int count = 5;Code language: C++ (cpp)

Expected Output:

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

Stored elements are: 10 20 30 40 50
+ Hint

Use malloc(5 * sizeof(int)) to allocate the block. Use a loop and either the scanf syntax with the address operator (&ptr[i]) or pointer arithmetic (scanf("%d", ptr + i);) for input.

+ Show Solution
#include <stdio.h>
#include <stdlib.h>

int main() {
    int count = 5;
    // Allocate memory for 5 integers
    int *arr_ptr = (int *)malloc(count * sizeof(int));

    if (arr_ptr == NULL) {
        printf("Memory allocation failed!\n");
        return 1;
    }

    printf("Enter %d integers:\n", count);
    // Input loop using pointer arithmetic
    for (int i = 0; i < count; i++) {
        printf("Element %d: ", i + 1);
        scanf("%d", arr_ptr + i); // (arr_ptr + i) is the address of the i-th element
    }

    printf("\nStored elements are: ");
    // Output loop using pointer arithmetic
    for (int i = 0; i < count; i++) {
        printf("%d ", *(arr_ptr + i)); // *(arr_ptr + i) is the value
    }
    printf("\n");

    free(arr_ptr);
    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • malloc(count * sizeof(int)) calculates the total required bytes (5×4=20 bytes on most 32/64-bit systems) and allocates it as a single contiguous block.
  • For input, scanf("%d", arr_ptr + i); passes the address of the i-th element to scanf, allowing the function to write the user’s input directly into that memory location.
  • For output, *(arr_ptr + i) dereferences the calculated address to retrieve the stored value.

Exercise 17: Using calloc

Problem Statement: Use calloc() to dynamically allocate memory for an array of 10 floating-point numbers. Print the first and last elements to verify that calloc automatically initializes all elements to zero. Then, free the memory.

Given:

int count = 10;Code language: C++ (cpp)

Expected Output:

Verifying calloc initialization (should be 0.00):
First element (float_arr[0]): 0.00
Last element (*(float_arr + 9)): 0.00
Element at index 5 after assignment: 3.14
+ Hint

calloc takes two arguments: the number of elements and the size of each element (calloc(num_elements, element_size)).

+ Show Solution
#include <stdio.h>
#include <stdlib.h>

int main() {
    int count = 10;
    float *float_arr = NULL;

    // Allocate memory for 10 floats, initialized to zero
    float_arr = (float *)calloc(count, sizeof(float));

    if (float_arr == NULL) {
        printf("Memory allocation failed!\n");
        return 1;
    }

    printf("Verifying calloc initialization (should be 0.00):\n");
    // Print the first element
    printf("First element (float_arr[0]): %.2f\n", float_arr[0]);
    // Print the last element using pointer arithmetic
    printf("Last element (*(float_arr + 9)): %.2f\n", *(float_arr + count - 1));

    // Assign a new value and print to show it's usable
    *(float_arr + 5) = 3.14f;
    printf("Element at index 5 after assignment: %.2f\n", float_arr[5]);

    free(float_arr);
    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • calloc(count, sizeof(float)) allocates the required memory (10 blocks of 4 bytes each) and guarantees that all 40 bytes are initialized to binary zero, which represents 0.0 for a float.
  • This is the primary difference from malloc(), which leaves the memory contents uninitialized (holding garbage values).
  • We verify the zero initialization by printing the first and last element before any assignment.

Exercise 18: Using realloc

Problem Statement:

  1. Allocate an initial array of 2 integers using malloc(), storing values 10 and 20.
  2. Use realloc() to increase the array size to 4 integers.
  3. Store values 30 and 40 in the two new slots.
  4. Print all 4 elements.

Given:

int current_size = 2;Code language: C++ (cpp)

Expected Output:

Initial size 2: 10, 20
New size 4: 10 20 30 40
+ Hint

realloc(old_ptr, new_size) either expands the existing block or allocates a new, larger block, copying the old data over. It returns the address of the new (potentially moved) block, so the result must be captured in a new or the original pointer.

+ Show Solution
#include <stdio.h>
#include <stdlib.h>

int main() {
    int *arr = NULL;
    int current_size = 2;

    // 1. Initial allocation for 2 elements
    arr = (int *)malloc(current_size * sizeof(int));
    if (arr == NULL) return 1;

    arr[0] = 10;
    arr[1] = 20;

    printf("Initial size %d: %d, %d\n", current_size, arr[0], arr[1]);

    // 2. Increase size to 4 elements using realloc
    current_size = 4;
    int *temp = (int *)realloc(arr, current_size * sizeof(int));

    if (temp == NULL) {
        printf("Reallocation failed!\n");
        free(arr);
        return 1;
    }
    arr = temp; // Update the pointer to the potentially new block address

    // 3. Store new values
    arr[2] = 30;
    arr[3] = 40;

    // 4. Print all 4 elements
    printf("New size %d: ", current_size);
    for (int i = 0; i < current_size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    free(arr);
    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • realloc is used to resize a previously allocated block. The existing data (10 and 20) is preserved.
  • We use a temporary pointer (temp) to safely capture the return value of realloc. If realloc fails, it returns NULL, but the original block (arr) is still valid and needs to be freed. Only if it succeeds do we update arr = temp;.
  • The new elements (30 and 40) are added using standard array notation, which works because the memory is contiguous.

Exercise 19: Memory Allocation Check

Problem Statement: Write a robust program that attempts to dynamically allocate a very large block of memory (e.g., 1 GB). Include a check for the NULL return value from malloc() and handle the memory allocation failure gracefully by printing an error message and exiting with a non-zero status code.

Expected Output:

Attempting to allocate 1073741824 bytes (approx 1 GB)...
Successfully allocated the large block at address: 0x72a7c8de3010
+ Hint

1 GB is 1024×1024×1024 bytes. Use a large number of elements multiplied by sizeof(int). The goal is to deliberately cause a failure on systems with limited resources.

+ Show Solution
#include <stdio.h>
#include <stdlib.h>

int main() {
    // Attempt to allocate 1 GB (1024 * 1024 * 256 * sizeof(int) if int is 4 bytes)
    // Adjust the size if needed to reliably fail on your system
    size_t size_in_bytes = (size_t)1024 * 1024 * 1024;
    void *large_block = NULL;

    printf("Attempting to allocate %zu bytes (approx 1 GB)...\n", size_in_bytes);

    // Attempt allocation
    large_block = malloc(size_in_bytes);

    // Crucial error check
    if (large_block == NULL) {
        // Graceful failure handling
        fprintf(stderr, "Error: Memory allocation failed! System ran out of memory.\n");
        return 1; // Return non-zero to indicate failure
    }

    printf("Successfully allocated the large block at address: %p\n", large_block);

    // Free the memory if successful
    free(large_block);
    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • The program requests a massive chunk of memory using malloc.
  • The error check if (large_block == NULL) is the standard way to verify DMA success. If the system cannot fulfill the request (due to fragmentation or lack of available RAM/swap space), malloc returns a NULL pointer.
  • If NULL is returned, the program prints an error to stderr and uses return 1; (or exit(1);) to signal the operating system that the program terminated with an error, demonstrating robust pointer usage.

Exercise 20: Introduction to Double Pointers

Problem Statement: Declare an integer variable (num), a pointer to the integer (ptr1), and a pointer to the pointer (double pointer, ptr2). Assign addresses correctly and print the final value of num using all three variables: num, *ptr1, and **ptr2.

Given:

int num = 77;Code language: C++ (cpp)

Expected Output:

Original value (num): 77
Value via *ptr1: 77
Value via **ptr2: 77

Address of num: 0x7ffdcdfc6664
Value stored in ptr1: 0x7ffdcdfc6664
Address of ptr1: 0x7ffdcdfc6668
Value stored in ptr2: 0x7ffdcdfc6668
+ Hint
  • ptr1 stores &num.
  • ptr2 stores &ptr1.
  • Use two dereference operators (**) on ptr2 to reach the value of num.
+ Show Solution
#include <stdio.h>

int main() {
    int num = 77;
    int *ptr1;      // Pointer to an integer
    int **ptr2;     // Pointer to a pointer to an integer

    ptr1 = &num;    // ptr1 stores the address of num
    ptr2 = &ptr1;   // ptr2 stores the address of ptr1

    printf("Original value (num): %d\n", num);

    // Accessing value through single pointer
    printf("Value via *ptr1: %d\n", *ptr1);

    // Accessing value through double pointer
    printf("Value via **ptr2: %d\n", **ptr2);

    // Demonstrating addresses
    printf("\nAddress of num: %p\n", &num);
    printf("Value stored in ptr1: %p\n", ptr1); // Same as address of num
    printf("Address of ptr1: %p\n", &ptr1);
    printf("Value stored in ptr2: %p\n", ptr2); // Same as address of ptr1

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • int **ptr2; declares a double pointer. It holds the address of another pointer variable (ptr1).
  • When using **ptr2, the first dereference (*ptr2) yields the value stored in ptr2, which is the address of num. This effectively becomes *(&num).
  • The second dereference (*(*ptr2)) then uses that address to retrieve the final value, 77. Double pointers are essential for modifying a pointer variable itself inside a function

Exercise 21: Function with Double Pointer

Problem Statement: Write a function allocate_memory that dynamically allocates memory for a single integer and stores the value 99 in it. The function must take a double pointer (int **) as an argument to ensure the pointer variable in the main function is updated with the address of the newly allocated memory.

Expected Output:

data_ptr address before call: (nil)
data_ptr address after call: 0x59d19bd8f6b0
Value accessed via data_ptr: 99
+ Hint

Inside the function, use the address held by the double pointer (*ptr_to_ptr) to store the address returned by malloc. Use two dereference operators (**) to set the value. Remember to check for malloc failure.

+ Show Solution
#include <stdio.h>
#include <stdlib.h>

// Takes a pointer to a pointer (int **)
void allocate_memory(int **ptr_to_ptr) {
    // Allocate memory for one integer
    int *new_ptr = (int *)malloc(sizeof(int));

    if (new_ptr == NULL) {
        fprintf(stderr, "Allocation failed in function.\n");
        // Optionally, set the main pointer to NULL on failure
        *ptr_to_ptr = NULL;
        return;
    }

    // Store the allocated address back into the pointer variable in main
    *ptr_to_ptr = new_ptr;

    // Store the value 99 in the newly allocated memory block
    **ptr_to_ptr = 99;
}

int main() {
    int *data_ptr = NULL; // Pointer starts as NULL

    printf("data_ptr address before call: %p\n", (void *)data_ptr);

    // Pass the ADDRESS of data_ptr
    allocate_memory(&data_ptr);

    printf("data_ptr address after call: %p\n", (void *)data_ptr);

    if (data_ptr != NULL) {
        printf("Value accessed via data_ptr: %d\n", *data_ptr);
        free(data_ptr);
    }

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • The goal is to modify the pointer variable data_ptr defined in main. Since C uses Pass by Value, we must pass the address of data_ptr, which is &data_ptr. This address is captured by the double pointer ptr_to_ptr.
  • *ptr_to_ptr = new_ptr; is the key line. The first dereference gets us to the data_ptr variable in main, and we assign the new memory address (new_ptr) to it.
  • **ptr_to_ptr = 99; dereferences twice: once to get the address stored in data_ptr, and again to access the value at that address, where 99 is stored.

Exercise 22: 2D Array Simulation

Problem Statement: Simulate a 2×3 2D array using a single pointer to dynamically allocated memory. Allocate memory for 6 integers. Use pointer arithmetic to access and print the value at the conceptual row 1, column 2 (index [1][2]).

Given:

const int ROWS = 2;
const int COLS = 3;Code language: C++ (cpp)

Expected Output:

Simulated 2x3 Array:
Value at index [1][2] (offset 5): 15
+ Hint

For a 2×3 array stored in a single contiguous block, the address of element [i][j] is calculated as base_address + (i * number_of_columns + j). Use i=1 and j=2 with 3 columns.

+ Show Solution
#include <stdio.h>
#include <stdlib.h>

int main() {
    const int ROWS = 2;
    const int COLS = 3;
    int *matrix_ptr = NULL;

    // Allocate memory for 2 * 3 = 6 integers
    matrix_ptr = (int *)malloc(ROWS * COLS * sizeof(int));
    if (matrix_ptr == NULL) return 1;

    // Fill the simulated array (just for demonstration)
    for (int i = 0; i < ROWS * COLS; i++) {
        *(matrix_ptr + i) = i + 10;
    }
    // Elements: 10, 11, 12, 13, 14, 15

    // Access element at [1][2]
    int row = 1;
    int col = 2;
    int index = row * COLS + col; // 1 * 3 + 2 = 5

    int value = *(matrix_ptr + index);

    printf("Simulated 2x3 Array:\n");
    printf("Value at index [%d][%d] (offset %d): %d\n", row, col, index, value);
    // Should print the 6th element (value 15, which is index 5)

    free(matrix_ptr);
    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • In C, a 2D array is stored contiguously in memory in row-major order.
  • We allocate a flat block of 6 integers. To find the i-th row, we must jump over all preceding rows, each of size COLS.
  • The formula i×COLS+j gives the single-dimensional offset from the start of the array.
  • *(matrix_ptr + index) uses pointer arithmetic to calculate the exact memory location and dereferences it to retrieve the value, mimicking the functionality of matrix[1][2].

Exercise 23: Swap Two Numbers

Problem Statement: Write a function swap(int *a, int *b) that swaps the values of two integers using their pointers. Demonstrate the swap in the main function.

Given:

int x = 100;
int y = 200;Code language: C++ (cpp)

Expected Output:

Before swap: x = 100, y = 200
After swap: x = 200, y = 100
+ Hint

The swap logic requires a temporary variable. All operations inside the function must use the dereference operator (*) to work directly with the values stored in the original memory locations.

+ Show Solution
#include <stdio.h>

// Function takes two integer pointers
void swap(int *a, int *b) {
    int temp;

    // Store the value pointed to by a
    temp = *a;

    // Store the value pointed to by b into the location pointed to by a
    *a = *b;

    // Store the temporary value into the location pointed to by b
    *b = temp;
}

int main() {
    int x = 100;
    int y = 200;

    printf("Before swap: x = %d, y = %d\n", x, y);

    // Pass the addresses (Pass by Reference)
    swap(&x, &y);

    printf("After swap: x = %d, y = %d\n", x, y);

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • This is a classic example of Pass by Reference using pointers. By passing &x and &y, the swap function receives the memory addresses of x and y.
  • Inside swap, the pointers a and b hold these addresses. Every access and modification is done via the dereference operator (*), ensuring the changes are made directly to the original variables x and y in the main function’s memory space.

Exercise 24: Return Multiple Values

Problem Statement: Write a function find_min_max that takes an integer array, its size, and two integer pointers (min_ptr and max_ptr). The function should find the minimum and maximum elements in the array and use the pointers to return these values to the caller.

Given:

int data[] = {15, 7, 22, 1, 9};Code language: C++ (cpp)

Expected Output:

The array is: {15, 7, 22, 1, 9}
Minimum value found: 1
Maximum value found: 22
+ Hint

Inside the function, initialize the min/max search using the first element. When a new min/max is found, use the dereference operator on min_ptr or max_ptr to store the value in the caller’s variables.

+ Show Solution
#include <stdio.h>

void find_min_max(int *arr, int size, int *min_ptr, int *max_ptr) {
    if (size <= 0) return;

    // Initialize min and max with the first element's value
    *min_ptr = arr[0];
    *max_ptr = arr[0];

    for (int i = 1; i < size; i++) {
        if (arr[i] < *min_ptr) {
            *min_ptr = arr[i]; // Update the minimum value in the caller's variable
        }
        if (arr[i] > *max_ptr) {
            *max_ptr = arr[i]; // Update the maximum value in the caller's variable
        }
    }
}

int main() {
    int data[] = {15, 7, 22, 1, 9};
    int size = 5;
    int min_val, max_val;

    // Pass the addresses of min_val and max_val
    find_min_max(data, size, &min_val, &max_val);

    printf("The array is: {15, 7, 22, 1, 9}\n");
    printf("Minimum value found: %d\n", min_val);
    printf("Maximum value found: %d\n", max_val);

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • Since C functions can only return a single value, pointers are used to pass variables by reference for output.
  • The main function passes &min_val and &max_val.
  • Inside find_min_max, min_ptr and max_ptr hold the addresses of min_val and max_val, respectively.
  • When a new minimum is found (e.g., 1), the line *min_ptr = arr[i]; directly writes the value 1 into the memory location of the original min_val variable in main.

Exercise 25: Pointer to a Function (Function Pointers)

Problem Statement: Declare a function pointer that can point to a function that takes two integers and returns an integer. Assign it to a simple add function. Call the add function using both its original name and the function pointer.

Given:

int x = 5, y = 3;Code language: C++ (cpp)

Expected Output:

Result from direct call (add): 8
Result from pointer call ((*ptr_to_add)): 8
Function address: 0x5984327c9149
Pointer value: 0x5984327c9149
+ Hint

The syntax for declaring a function pointer is return_type (*pointer_name)(argument_list).

+ Show Solution
#include <stdio.h>

// Function to be pointed to
int add(int a, int b) {
    return a + b;
}

int main() {
    // 1. Declare the function pointer
    int (*ptr_to_add)(int, int);

    // 2. Assign the function address (using just the function name)
    ptr_to_add = add;

    int x = 5, y = 3;
    int result1, result2;

    // Call 1: Direct call
    result1 = add(x, y);

    // Call 2: Call using the function pointer (dereference is optional but clearer)
    result2 = (*ptr_to_add)(x, y);

    printf("Result from direct call (add): %d\n", result1);
    printf("Result from pointer call ((*ptr_to_add)): %d\n", result2);
    printf("Function address: %p\n", (void *)add);
    printf("Pointer value: %p\n", (void *)ptr_to_add);

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • int (*ptr_to_add)(int, int); declares ptr_to_add as a pointer that points to a function returning an int and taking two int arguments. The parentheses around *ptr_to_add are crucial to distinguish it from a function declaration returning a pointer.
  • ptr_to_add = add; assigns the memory address of the add function to the pointer.
  • Calling the function via the pointer ((*ptr_to_add)(x, y)) instructs the program to execute the code stored at the address contained in ptr_to_add. Function pointers are the basis for callbacks and dynamic function dispatch.

Exercise 26: Structure Pointer

Problem Statement: Define a structure Point with members x and y. Declare a variable of this structure and a pointer to it. Access and modify the structure members using the arrow operator (->).

Given:

struct Point p1 = {10, 20}; // Structure variableCode language: C++ (cpp)

Expected Output:

Original Point p1: (10, 20)
Modified Point p1 via pointer:
X coordinate (p_ptr->x): 5
Y coordinate (p_ptr->y): 15
Original variable p1 after modification: (5, 15)
+ Hint

The arrow operator (->) is syntactic sugar for dereferencing a structure pointer and accessing a member: ptr->member is equivalent to (*ptr).member.

+ Show Solution
#include <stdio.h>

struct Point {
    int x;
    int y;
};

int main() {
    struct Point p1 = {10, 20}; // Structure variable
    struct Point *p_ptr = &p1;  // Pointer to the structure

    printf("Original Point p1: (%d, %d)\n", p1.x, p1.y);

    // Access and modify members using the arrow operator (->)
    p_ptr->x = 5;
    p_ptr->y = 15;

    printf("Modified Point p1 via pointer:\n");
    printf("X coordinate (p_ptr->x): %d\n", p_ptr->x);
    printf("Y coordinate (p_ptr->y): %d\n", p_ptr->y);

    // Verify the original variable is changed
    printf("Original variable p1 after modification: (%d, %d)\n", p1.x, p1.y);

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • struct Point *p_ptr = &p1; initializes the structure pointer to hold the address of the structure variable p1.
  • The arrow operator (->) is specifically designed to work with structure pointers. It automatically dereferences the pointer and then accesses the specified member.
  • p_ptr->x = 5; is the standard, readable way to modify the x member of the structure that p_ptr is pointing to.

Exercise 27: Array of Structures

Problem Statement: Define a struct Student with id (int) and gpa (float). Create an array of 3 Student structures and initialize them. Use a structure pointer to iterate through the array and print the id and gpa of each student.

Given:

// Array of 3 structures
struct Student class_list[3] = {
      {101, 3.5},
      {102, 3.8},
      {103, 3.2}
 };Code language: C++ (cpp)

Expected Output:

Student Records:
Student 1: ID = 101, GPA = 3.5
Student 2: ID = 102, GPA = 3.8
Student 3: ID = 103, GPA = 3.2
+ Hint

The array name is a pointer to the first structure. You can use pointer arithmetic to move the pointer to the next structure: ptr++ will jump by sizeof(struct Student) bytes.

+ Show Solution
#include <stdio.h>

struct Student {
    int id;
    float gpa;
};

int main() {
    // Array of 3 structures
    struct Student class_list[3] = {
        {101, 3.5},
        {102, 3.8},
        {103, 3.2}
    };

    // Pointer initialized to the start of the array
    struct Student *s_ptr = class_list;

    printf("Student Records:\n");
    for (int i = 0; i < 3; i++) {
        printf("Student %d: ID = %d, GPA = %.1f\n",
               i + 1,
               s_ptr->id,    // Access current student's ID
               s_ptr->gpa);  // Access current student's GPA

        s_ptr++; // Move the pointer to the next student structure
    }

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • The array name class_list acts as a base pointer to the first element (class_list[0]).
  • The pointer s_ptr is initialized to this base address.
  • Inside the loop, s_ptr->id accesses the members of the structure that the pointer currently points to.
  • Pointer arithmetic is used with s_ptr++. Since s_ptr is a struct Student *, incrementing it causes the pointer to advance by sizeof(struct Student) bytes, correctly moving it to the start of the next structure in the array.

Exercise 28: Dynamic Structure Allocation

Problem Statement: Define a struct Circle with a radius (float). Dynamically allocate memory for a single Circle structure using malloc(). Populate its members, print the area (Area = π×r2), and then free the memory.

Given:

struct Circle {
    float radius;
};Code language: C++ (cpp)

Expected Output:

Dynamically allocated circle:
Radius: 12.50
Area: 490.87
+ Hint

Use malloc(sizeof(struct Circle)) for allocation. Use the arrow operator (->) to set and access the members of the dynamically allocated structure.

+ Show Solution
#include <stdio.h>
#include <stdlib.h>
#define PI 3.14159

struct Circle {
    float radius;
};

int main() {
    struct Circle *c_ptr = NULL;

    // Allocate memory for one Circle structure
    c_ptr = (struct Circle *)malloc(sizeof(struct Circle));

    if (c_ptr == NULL) {
        fprintf(stderr, "Memory allocation failed.\n");
        return 1;
    }

    // Set radius using the arrow operator
    c_ptr->radius = 12.5f;

    // Calculate and print the area
    float area = PI * (c_ptr->radius) * (c_ptr->radius);

    printf("Dynamically allocated circle:\n");
    printf("Radius: %.2f\n", c_ptr->radius);
    printf("Area: %.2f\n", area);

    // Release the memory
    free(c_ptr);
    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • This combines Dynamic Memory Allocation (DMA) with structures. malloc reserves a block large enough for one Circle structure.
  • The base address of this block is assigned to c_ptr.
  • Since c_ptr is a pointer, we must use the arrow operator (c_ptr->radius) to access and modify the member data within the dynamically created structure.
  • Calling free(c_ptr) is mandatory to prevent a memory leak, as the memory was allocated from the heap.

Exercise 29: Generic Pointers (void *)

Problem Statement: Write a function print_generic_data that takes a generic pointer (void *) and an integer indicating the data type (1 for int, 2 for float). Inside the function, cast the void * to the correct data type pointer and print the value it holds.

Given:

int i_val = 123;
float f_val = 45.67f;Code language: C++ (cpp)

Expected Output:

Data type: Integer, Value: 123
Data type: Float, Value: 45.67
+ Hint

The void * pointer can hold the address of any data type. You must explicitly cast it to the correct pointer type (e.g., (int *)data_ptr) before dereferencing (*) it.

+ Show Solution
#include <stdio.h>

// Function takes a generic pointer and a type identifier
void print_generic_data(void *data_ptr, int type) {
    if (type == 1) {
        // Cast void* to int* and then dereference
        int value = *((int *)data_ptr);
        printf("Data type: Integer, Value: %d\n", value);
    } else if (type == 2) {
        // Cast void* to float* and then dereference
        float value = *((float *)data_ptr);
        printf("Data type: Float, Value: %.2f\n", value);
    } else {
        printf("Unknown data type.\n");
    }
}

int main() {
    int i_val = 123;
    float f_val = 45.67f;

    // Pass the address of the integer variable
    print_generic_data(&i_val, 1);

    // Pass the address of the float variable
    print_generic_data(&f_val, 2);

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • A void * pointer is a generic pointer; it holds an address but has no information about the size or type of data at that address.
  • When passing the address (&i_val) to the function, it is implicitly cast to void *.
  • Inside the function, the program relies on the type argument to correctly cast the void * back to a specific pointer type, such as (int *)data_ptr. Without this cast, the dereference operator (*) wouldn’t know how many bytes to read from that address.

Exercise 30: Pointer Arithmetic Boundary

Problem Statement: Write a program demonstrating the effect of adding 1 to an integer pointer and adding 1 to a character pointer. Print the original and resulting addresses to illustrate how pointer arithmetic scales according to the data type size.

Expected Output:

Int Pointer Size: 4 bytes
Char Pointer Size: 1 bytes

--- Integer Pointer Arithmetic ---
i_ptr original address: 0x7ffd3446e3cc
i_ptr new address: 0x7ffd3446e3d0

--- Character Pointer Arithmetic ---
c_ptr original address: 0x7ffd3446e3d6
c_ptr new address: 0x7ffd3446e3d7
+ Hint

Find the difference between the starting address and the address after incrementing the pointer. The difference for the char * should be 1 byte, while the difference for the int * should be sizeof(int) bytes.

+ Show Solution
#include <stdio.h>

int main() {
    int i_arr[2];      // Array for integer pointer
    char c_arr[2];     // Array for character pointer

    int *i_ptr = i_arr;    // Start at i_arr[0]
    char *c_ptr = c_arr;   // Start at c_arr[0]

    printf("Int Pointer Size: %zu bytes\n", sizeof(int));
    printf("Char Pointer Size: %zu bytes\n", sizeof(char)); // Should be 1

    printf("\n--- Integer Pointer Arithmetic ---\n");
    printf("i_ptr original address: %p\n", (void *)i_ptr);

    i_ptr++; // Pointer arithmetic

    printf("i_ptr new address:      %p\n", (void *)i_ptr);
    // Note: The difference will be sizeof(int) bytes (e.g., 4 bytes)

    printf("\n--- Character Pointer Arithmetic ---\n");
    printf("c_ptr original address: %p\n", (void *)c_ptr);

    c_ptr++; // Pointer arithmetic

    printf("c_ptr new address:      %p\n", (void *)c_ptr);
    // Note: The difference will be sizeof(char) bytes (1 byte)

    return 0;
}Code language: C++ (cpp)
Run

Explanation:

  • Pointer Arithmetic is not simple addition. When you increment a pointer, the compiler automatically scales the increment by the size of the data type the pointer points to.
  • i_ptr++ moves the pointer forward by sizeof(int) bytes (typically 4), ensuring it points correctly to the next integer element in memory.
  • c_ptr++ moves the pointer forward by sizeof(char) bytes (always 1), ensuring it points correctly to the next character.
  • This scaling is fundamental to array traversal and the close relationship between arrays and pointers in C.

Filed Under: C Programming Exercises

Did you find this page helpful? Let others know about it. Sharing helps me continue to create free Python resources.

TweetF  sharein  shareP  Pin

About Vishal

Image

I’m Vishal Hule, the Founder of PYnative.com. As a Python developer, I enjoy assisting students, developers, and learners. Follow me on Twitter.

Related Tutorial Topics:

C Programming Exercises

Python Exercises and Quizzes

Free coding exercises and quizzes cover Python basics, data structure, data analytics, and more.

  • 15+ Topic-specific Exercises and Quizzes
  • Each Exercise contains 10 questions
  • Each Quiz contains 12-15 MCQ
Exercises
Quizzes

Leave a Reply Cancel reply

your email address will NOT be published. all comments are moderated according to our comment policy.

Use <pre> tag for posting code. E.g. <pre> Your entire code </pre>

In: C Programming Exercises
TweetF  sharein  shareP  Pin

  C Exercises

  • All C Exercises
  • C Exercise for Beginners
  • C Variable and Data Type Exercise
  • C Loops Exercise
  • C Functions Exercise
  • C Arrays Exercise
  • C String Exercise
  • C Pointers Exercise
  • C File Handling Exercise
  • C Structures and Unions Exercise

All Coding Exercises

C Exercises Python Exercises

About PYnative

PYnative.com is for Python lovers. Here, You can get Tutorials, Exercises, and Quizzes to practice and improve your Python skills.

Explore Python

  • Learn Python
  • Python Basics
  • Python Databases
  • Python Exercises
  • Python Quizzes
  • Online Python Code Editor
  • Python Tricks

Follow Us

To get New Python Tutorials, Exercises, and Quizzes

  • Twitter
  • Facebook
  • Sitemap

Legal Stuff

  • About Us
  • Contact Us

We use cookies to improve your experience. While using PYnative, you agree to have read and accepted our:

  • Terms Of Use
  • Privacy Policy
  • Cookie Policy

Copyright © 2018–2025 pynative.com

Advertisement