Unit III Pointers Part B and Dynamic Memory Allocation
Unit III Pointers Part B and Dynamic Memory Allocation
Pointers and Arrays Overview: In C, pointers and arrays have a close relationship. A pointer can
store the address of an array element, allowing efficient access and manipulation. An array
name acts as a pointer to the first element, enabling pointer arithmetic.
#include <stdio.h>
int main() {
int arr[3] = {10, 20, 30};
int *ptr = arr;
Output Explanation:
The pointer ptr accesses each element in the array arr using pointer arithmetic. *(ptr + i)
retrieves arr[i].
---
#include <stdio.h>
int main() {
int arr[3] = {5, 15, 25};
int *ptr = arr;
Output Explanation:
Each array element is modified by adding 10 through the pointer ptr. The changes reflect in the
original array arr.
---
#include <stdio.h>
int main() {
int arr[3] = {3, 6, 9};
Output Explanation:
Since arr acts as a pointer to its first element, *(arr + i) accesses each element directly.
---
#include <stdio.h>
int main() {
int arr[3] = {100, 200, 300};
Output Explanation:
Each element’s address is printed, showing how the array elements are sequentially stored in
memory.
---
2. Passing Arrays to Functions
Overview:
When an array is passed to a function, it is effectively a pointer to the array's first element,
allowing the function to access and modify elements.
#include <stdio.h>
int main() {
int arr[3] = {4, 8, 12};
display(arr, 3);
return 0;
}
Output Explanation:
display receives arr as a pointer and prints each element.
---
#include <stdio.h>
int main() {
int arr[3] = {2, 4, 6};
modify(arr, 3);
for (int i = 0; i < 3; i++) {
printf("arr[%d] = %d\n", i, arr[i]);
}
return 0;
}
Output Explanation:
modify changes arr elements directly, demonstrating array modifications within a function.
---
#include <stdio.h>
int main() {
int arr[3] = {5, 15, 10};
printf("Max element: %d\n", findMax(arr, 3));
return 0;
}
Output Explanation:
The function finds the maximum value in arr without needing to return the array itself.
---
#include <stdio.h>
int main() {
int arr[4] = {1, 2, 3, 4};
printf("Sum of elements: %d\n", sum(arr, 4));
return 0;
}
Output Explanation:
The sum function calculates the total sum of arr elements.
---
3. Array of Pointers
Overview:
An array of pointers holds the addresses of multiple variables or strings, each pointing to distinct
data.
#include <stdio.h>
int main() {
const char *cities[] = {"New York", "Paris", "Tokyo"};
Output Explanation:
Each cities[i] points to a different string, allowing efficient handling of multiple strings.
---
int main() {
int a = 5, b = 10, c = 15;
int *arr[3] = {&a, &b, &c};
Output Explanation:
Each element of arr points to an integer, showing how arrays of pointers manage different
variables.
---
4. Function Pointers
#include <stdio.h>
void greet() {
printf("Hello!\n");
}
int main() {
void (*func_ptr)() = greet; // Declaring a function pointer
func_ptr(); // Calling the function through the pointer
return 0;
}
Output Explanation:
In this example, func_ptr is a pointer to the greet function. Calling func_ptr() executes greet,
printing "Hello!".
---
#include <stdio.h>
int main() {
void (*func_ptr)(int, int) = add;
func_ptr(5, 10); // Calling add with parameters 5 and 10
return 0;
}
Output Explanation:
func_ptr is a pointer to add. Calling func_ptr(5, 10) executes add, outputting "Sum: 15".
---
#include <stdio.h>
int main() {
void (*operations[])(int, int) = {add, subtract};
operations[0](10, 5); // Calls add
operations[1](10, 5); // Calls subtract
return 0;
}
Output Explanation:
An array of function pointers (operations) holds add and subtract. operations[0](10, 5) calls add,
and operations[1](10, 5) calls subtract.
---
Example 4: Passing Function Pointers as Arguments
#include <stdio.h>
int main() {
executeOperation(multiply, 4, 5);
return 0;
}
Output Explanation:
executeOperation receives a function pointer and calls it with x and y. Here, it calls multiply,
outputting "Product: 20".
---
6. Call by Reference
#include <stdio.h>
int main() {
int x = 50;
changeValue(&x);
printf("Modified x: %d\n", x);
return 0;
}
Output Explanation:
The changeValue function receives the address of x and changes its value to 100. The original
variable x is modified, and the output is "Modified x: 100".
---
#include <stdio.h>
int main() {
int x = 5, y = 10;
swap(&x, &y);
printf("After swapping: x = %d, y = %d\n", x, y);
return 0;
}
Output Explanation:
The swap function receives pointers to x and y, allowing it to swap their values directly. The
output shows "After swapping: x = 10, y = 5".
---
#include <stdio.h>
int main() {
int numbers[] = {1, 2, 3};
increaseElements(numbers, 3);
for (int i = 0; i < 3; i++) {
printf("numbers[%d] = %d\n", i, numbers[i]);
}
return 0;
}
Output Explanation:
The function increaseElements modifies numbers directly, increasing each element by 10. The
output reflects these changes.
---
7. Call by Value
#include <stdio.h>
int main() {
int x = 50;
modify(x);
printf("Unmodified x: %d\n", x);
return 0;
}
Output Explanation:
modify changes only the copy of x, so the original x remains 50. The output is "Unmodified x:
50".
---
int main() {
int x = 3, y = 7;
sum(x, y);
printf("x: %d, y: %d\n", x, y);
return 0;
}
Output Explanation:
The function calculates the sum of x and y, but their original values are unchanged outside the
function.
---
My apologies for that! Here is a detailed section on Pointers to Pointers with definitions,
descriptions, and multiple examples including code and output explanations.
---
8. Pointers to Pointers
A pointer to a pointer can indirectly access values that are two levels away in memory. They are
often used in complex data structures and in situations requiring indirect referencing, such as
modifying pointer values inside functions.
---
int main() {
int x = 10;
int *p = &x; // p is a pointer to x
int **pp = &p; // pp is a pointer to p
return 0;
}
Output Explanation:
---
#include <stdio.h>
int main() {
int x = 10;
int *p = &x;
int **pp = &p;
Output Explanation:
In this example, the modify function takes a double pointer pp, which points to p, and modifies
the value of x by setting **pp to 20. The original x is changed, resulting in the output "Modified x:
20".
---
#include <stdio.h>
#include <stdlib.h>
int main() {
int rows = 2, cols = 3;
int **arr = (int **)malloc(rows * sizeof(int *)); // Allocate array of int pointers
return 0;
}
Output Explanation:
This program creates a 2D array dynamically using pointers to pointers:
1. arr is a double pointer pointing to an array of integer pointers (each representing a row).
---
#include <stdio.h>
int main() {
int a = 5, b = 15;
int *p = &a;
int **pp = &p;
return 0;
}
Output Explanation:
This program demonstrates how a double pointer can change which variable a pointer points to.
---
Dynamic Memory Allocation in C
Dynamic memory allocation allows a program to request memory from the heap at runtime,
unlike static memory allocation, which is determined at compile time. C provides several
functions for dynamic memory management: malloc(), calloc(), realloc(), and free().
Dynamic memory allocation is crucial when the size of data structures like arrays or linked lists
cannot be determined until runtime. The functions mentioned allocate memory in the "heap"
region, which the program manages explicitly.
Syntax:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr;
ptr = (int *)malloc(sizeof(int) * 3); // Allocates memory for 3 integers
Output Explanation:
Since malloc() does not initialize memory, the output will show random garbage values. Each
memory location contains whatever data was previously stored there.
---
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr;
ptr = (int *)malloc(sizeof(int) * 3); // Allocates memory for 3 integers
Output Explanation:
The output will be 1 2 3, as we explicitly set values in allocated memory. This ensures consistent
output.
---
Syntax:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr;
ptr = (int *)calloc(3, sizeof(int)); // Allocates memory for 3 integers, initialized to 0
Output Explanation:
Output will be 0 0 0, as calloc() initializes all allocated memory to zero, unlike malloc().
---
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = (int *)calloc(5, sizeof(int)); // Allocates memory for an array of 5 integers
Output Explanation:
The output is 0 2 4 6 8. The array is initialized to zero, and then each element is set to double its
index.
---
4. realloc() (Reallocation)
Syntax:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = (int *)malloc(2 * sizeof(int));
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
Output Explanation:
The output will be 1 2 3 4. The realloc() function expands the memory block, preserving the
original values, and allows us to add more data.
---
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = (int *)malloc(5 * sizeof(int));
for (int i = 0; i < 5; i++) {
arr[i] = i + 1;
}
Output Explanation:
Output will be 1 2 3. The array size is reduced, and the first three elements are retained. The
last two elements are discarded.
---
Syntax:
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr = (int *)malloc(3 * sizeof(int));
if (ptr == NULL) {
printf("Memory allocation failed\n");
return 1;
}
Output Explanation:
No specific output, but memory allocated to ptr is freed, and further access is prevented,
avoiding memory leaks.
---
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = (int *)calloc(3, sizeof(int));
Output Explanation:
The memory allocated by calloc() is released with free(). No output is expected, but it ensures
resources are properly managed.
---
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr = (int *)malloc(3 * sizeof(int));
arr = (int *)realloc(arr, 5 * sizeof(int)); // Expands memory
Output Explanation:
This ensures all dynamically allocated memory is freed, preventing memory leaks.
---
Additional Topic
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr = (int*)malloc(sizeof(int) * 3);
ptr[0] = 1;
ptr[1] = 2;
ptr[2] = 3;
free(ptr);
return 0;
}
Output Explanation:
Memory is allocated for 3 integers, and values are assigned. free(ptr) releases the memory after
use.
---
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr = (int*)calloc(3, sizeof(int)); // Allocates zero-initialized memory
free(ptr);
return 0;
}
Output Explanation:
calloc allocates and initializes memory to zero. The output confirms that ptr values are initially
zero.
---
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr = (int*)malloc(2 * sizeof(int));
ptr[0] = 5;
ptr[1] = 10;
free(ptr);
return 0;
}
Output Explanation:
realloc expands ptr to hold more values. The output shows the updated array after reallocation.