Pointers and Dynamic Memory Allocation in C - Questions and Answers

Basic Concepts of Pointers

1. How is a pointer variable different from a normal variable?

A pointer variable is different from a normal variable in the following ways:

Normal Variable Pointer Variable
Stores actual data values Stores memory addresses of other variables
Declared with data type (int, char, float, etc.) Declared with data type followed by * (int *, char *, etc.)
Accessed directly by name Accessed using dereference operator (*) to get the value at the stored address
Example: int x = 5; Example: int *ptr = &x;
2. Why is dynamic memory allocation an efficient memory management technique?

Dynamic memory allocation is efficient because:

  • Memory Utilization: It allows programs to request memory at runtime, using only what's needed
  • Flexibility: Memory can be allocated and deallocated as required during program execution
  • Avoids Waste: Prevents reserving fixed memory that might not be fully utilized
  • Data Structures: Essential for creating dynamic data structures like linked lists, trees, etc.
  • Lifetime Control: Memory remains allocated until explicitly freed, giving control over object lifetimes

Functions like malloc(), calloc(), realloc(), and free() are used for dynamic memory management in C.

3. How many bytes are needed to store an int pointer variable? Is it the same for a char pointer variable? Write a simple C program to explain your answer.

The size of a pointer variable depends on the system architecture, not the data type it points to. On most modern systems:

  • 32-bit systems: 4 bytes for any pointer
  • 64-bit systems: 8 bytes for any pointer

Yes, both int pointer and char pointer variables require the same amount of memory because they both store memory addresses.

#include <stdio.h>

int main() {
    int num = 10;
    char ch = 'A';
    
    int *intPtr = #
    char *charPtr = &ch;
    
    printf("Size of int pointer: %zu bytes\n", sizeof(intPtr));
    printf("Size of char pointer: %zu bytes\n", sizeof(charPtr));
    printf("Size of void pointer: %zu bytes\n", sizeof(void*));
    
    return 0;
}

Output (on a typical 64-bit system):
Size of int pointer: 8 bytes
Size of char pointer: 8 bytes
Size of void pointer: 8 bytes

Code Output Analysis

4. Write the output of the following code segments:

a.

int *ptr, x = 9;
ptr = &x;
printf("\n %d", (*ptr)++);

Output: 9

Explanation: (*ptr)++ returns the current value (9) and then increments x to 10.

b.

int *ptr, x = 9;
ptr = &x;
printf("\n %d", (*ptr)++);
printf("\n %d", *ptr);

Output:
9
10

Explanation: First printf outputs 9 (then increments x to 10), second printf outputs the new value 10.

c.

int *ptr, x = 9;
ptr = &x;
int y = ++(*ptr);
printf("\n %d", y);

Output: 10

Explanation: ++(*ptr) increments x to 10 first, then assigns 10 to y.

d.

char *ptr, x = 'A';
ptr = &x;
char y = *ptr;
printf("\n %c", y);

Output: A

Explanation: y gets the value at the address stored in ptr, which is 'A'.

e.

char *ptr, x = 'A';
ptr = &x;
char y = (*ptr)++;
printf("\n %c", y);

Output: A

Explanation: (*ptr)++ returns current value 'A' (then increments x to 'B'), so y becomes 'A'.

f.

char *ptr, x = 'A';
ptr = &x;
char y = ++(*ptr);
printf("\n %c", y);

Output: B

Explanation: ++(*ptr) increments x to 'B' first, then assigns 'B' to y.

g.

char *ptr, x = 'A';
ptr = &x;
char *y;
y = ptr;
printf("\n %c", ++(*y));

Output: B

Explanation: y points to the same address as ptr. ++(*y) increments the value at that address from 'A' to 'B' and returns 'B'.

Dynamic Memory Programs

5. Write a C program to dynamically allocate memory for an array to store 10 integers and display the first 5 out of them.
#include <stdio.h>
#include <stdlib.h>

int main() {
    int *arr;
    int n = 10;
    
    // Dynamically allocate memory for 10 integers
    arr = (int*)malloc(n * sizeof(int));
    
    if (arr == NULL) {
        printf("Memory allocation failed!\n");
        return 1;
    }
    
    // Initialize array with values
    for (int i = 0; i < n; i++) {
        arr[i] = (i + 1) * 10;
    }
    
    // Display first 5 elements
    printf("First 5 elements: ");
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    // Free the allocated memory
    free(arr);
    
    return 0;
}

Output: First 5 elements: 10 20 30 40 50

6. Write a C program to dynamically allocate memory for an array to store runs scored by Virat Kohli in the last ten ODI cricket matches. Write a function to find the maximum one.
#include <stdio.h>
#include <stdlib.h>

// Function to find maximum runs
int findMaxRuns(int *runs, int n) {
    int max = runs[0];
    for (int i = 1; i < n; i++) {
        if (runs[i] > max) {
            max = runs[i];
        }
    }
    return max;
}

int main() {
    int *runs;
    int n = 10;
    
    // Dynamically allocate memory for 10 matches
    runs = (int*)malloc(n * sizeof(int));
    
    if (runs == NULL) {
        printf("Memory allocation failed!\n");
        return 1;
    }
    
    // Input runs for 10 matches
    printf("Enter runs scored by Virat Kohli in last 10 ODIs:\n");
    for (int i = 0; i < n; i++) {
        printf("Match %d: ", i + 1);
        scanf("%d", &runs[i]);
    }
    
    // Find and display maximum runs
    int maxRuns = findMaxRuns(runs, n);
    printf("\nMaximum runs scored: %d\n", maxRuns);
    
    // Free the allocated memory
    free(runs);
    
    return 0;
}
7. Write a C program and define a function that takes the length of your name as an input parameter and then allocates memory dynamically to store your name. Write another function to display the name.
#include <stdio.h>
#include <stdlib.h>

// Function to allocate memory for name
char* allocateName(int length) {
    char *name = (char*)malloc((length + 1) * sizeof(char));
    if (name == NULL) {
        printf("Memory allocation failed!\n");
        return NULL;
    }
    return name;
}

// Function to display name
void displayName(char *name) {
    printf("Name: %s\n", name);
}

int main() {
    int nameLength;
    char *myName;
    
    printf("Enter the length of your name: ");
    scanf("%d", &nameLength);
    
    // Allocate memory for name
    myName = allocateName(nameLength);
    
    if (myName != NULL) {
        printf("Enter your name: ");
        scanf("%s", myName);
        
        // Display the name
        displayName(myName);
        
        // Free the allocated memory
        free(myName);
    }
    
    return 0;
}

Advanced Applications

8. Write a C program to store some integer variables in an array. Then write functions to:
  1. Calculate the number of even numbers in the array
  2. Dynamically allocate memory to a new array to store only the even numbers
  3. Copy the even numbers from the first array to the second one
#include <stdio.h>
#include <stdlib.h>

// Function to count even numbers
int countEvenNumbers(int arr[], int size) {
    int count = 0;
    for (int i = 0; i < size; i++) {
        if (arr[i] % 2 == 0) {
            count++;
        }
    }
    return count;
}

// Function to copy even numbers to new array
void copyEvenNumbers(int source[], int sourceSize, int dest[]) {
    int j = 0;
    for (int i = 0; i < sourceSize; i++) {
        if (source[i] % 2 == 0) {
            dest[j] = source[i];
            j++;
        }
    }
}

// Function to display array
void displayArray(int arr[], int size, char *name) {
    printf("%s array: ", name);
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    int firstArray[] = {2, 7, 4, 9, 6, 3, 8, 1, 5, 10};
    int firstSize = sizeof(firstArray) / sizeof(firstArray[0]);
    
    // Display first array
    displayArray(firstArray, firstSize, "First");
    
    // Count even numbers
    int evenCount = countEvenNumbers(firstArray, firstSize);
    printf("Number of even numbers: %d\n", evenCount);
    
    // Dynamically allocate memory for even numbers
    int *secondArray = (int*)malloc(evenCount * sizeof(int));
    
    if (secondArray == NULL) {
        printf("Memory allocation failed!\n");
        return 1;
    }
    
    // Copy even numbers to new array
    copyEvenNumbers(firstArray, firstSize, secondArray);
    
    // Display second array
    displayArray(secondArray, evenCount, "Second");
    
    // Free the allocated memory
    free(secondArray);
    
    return 0;
}

Output:
First array: 2 7 4 9 6 3 8 1 5 10
Number of even numbers: 5
Second array: 2 4 6 8 10

9. Write a C program to store some integer variables in an array. Then write functions to:
  1. Calculate the number of non-zero elements that are divisible by 3
  2. Dynamically allocate memory to a new array to store only those elements
  3. Copy the selected elements from the first array to the second one
  4. Calculate the summation of these elements
#include <stdio.h>
#include <stdlib.h>

// Function to count non-zero elements divisible by 3
int countDivisibleBy3(int arr[], int size) {
    int count = 0;
    for (int i = 0; i < size; i++) {
        if (arr[i] != 0 && arr[i] % 3 == 0) {
            count++;
        }
    }
    return count;
}

// Function to copy elements divisible by 3 to new array
void copyDivisibleBy3(int source[], int sourceSize, int dest[]) {
    int j = 0;
    for (int i = 0; i < sourceSize; i++) {
        if (source[i] != 0 && source[i] % 3 == 0) {
            dest[j] = source[i];
            j++;
        }
    }
}

// Function to calculate sum of array elements
int calculateSum(int arr[], int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += arr[i];
    }
    return sum;
}

// Function to display array
void displayArray(int arr[], int size, char *name) {
    printf("%s array: ", name);
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    int firstArray[] = {2, 4, 0, 9, 1, 9, 8, 6};
    int firstSize = sizeof(firstArray) / sizeof(firstArray[0]);
    
    // Display first array
    displayArray(firstArray, firstSize, "First");
    
    // Count elements divisible by 3
    int count = countDivisibleBy3(firstArray, firstSize);
    printf("Number of non-zero elements divisible by 3: %d\n", count);
    
    // Dynamically allocate memory for selected elements
    int *secondArray = (int*)malloc(count * sizeof(int));
    
    if (secondArray == NULL) {
        printf("Memory allocation failed!\n");
        return 1;
    }
    
    // Copy selected elements to new array
    copyDivisibleBy3(firstArray, firstSize, secondArray);
    
    // Display second array
    displayArray(secondArray, count, "Second");
    
    // Calculate and display sum
    int sum = calculateSum(secondArray, count);
    printf("Summation: %d\n", sum);
    
    // Free the allocated memory
    free(secondArray);
    
    return 0;
}

Output:
First array: 2 4 0 9 1 9 8 6
Number of non-zero elements divisible by 3: 3
Second array: 9 9 6
Summation: 24