Module 4: Chapter 5 - Pointers Continued
Pointers to Functions
In C, functions occupy memory and have an address, just like variables. A pointer that holds the address of a function is known as a function pointer. Once assigned, the function can be invoked using this pointer. Function pointers are powerful because they let you:
- Call a function through a pointer
- Pass functions as arguments to other functions
- Create arrays of functions for efficient operation selection
Declaring a Function Pointer
A function pointer must specify the function's return type and parameter types.
int (*p)(const char*, const char*);
Assigning a Function to Pointer
The function name without parentheses gives its address.
p = strcmp;
Calling a Function Using Pointer
Two valid styles:
(*p)(a, b);
p(a, b);
Example Usage
#include <stdio.h>
#include <string.h>
void check(char *a, char *b, int (*cmp)(const char*, const char*));
int main() {
int (*p)(const char*, const char*);
p = strcmp;
check("Hello", "Hello", p);
return 0;
}
void check(char *a, char *b, int (*cmp)(const char*, const char*)) {
if((*cmp)(a, b) == 0) printf("Equal");
else printf("Not Equal");
}
Why Use Function Pointers?
- Allows dynamic selection of different functions during runtime.
- Useful in interpreters, callback systems, event handling, algorithm swapping.
- Enables arrays of function pointers for menu-driven or modular designs.
Function pointers are extremely versatile in advanced C programming and help in writing flexible, modular, and scalable applications.
Dynamic Memory Allocation
Definition
Dynamic Memory Allocation (DMA) in C allows a program to request memory at runtime. The allocated memory comes from the heap and remains available until it is explicitly released by the programmer.
- Memory is allocated during program execution.
- Helps manage memory efficiently when size is not known in advance.
- Requires explicit allocation and deallocation.
- Defined in the
<stdlib.h>header file.
Dynamic Memory Allocation Functions
C provides the following standard library functions for dynamic memory management:
malloc()calloc()realloc()free()
1. malloc() - Memory Allocation
malloc() allocates a single block of memory of the specified size
in bytes and returns a pointer to the allocated memory.
Syntax
ptr = (type *) malloc(size_in_bytes);
Example
int *p;
p = (int *) malloc(5 * sizeof(int));
if(p == NULL)
printf("Memory allocation failed");
else
printf("Memory allocated successfully");
- Memory contents are uninitialized (garbage values).
- Returns
NULLif allocation fails.
2. calloc() - Contiguous Allocation
calloc() allocates memory for multiple elements and
initializes all bytes to zero.
Syntax
ptr = (type *) calloc(n, sizeof(type));
Example
int *p;
p = (int *) calloc(5, sizeof(int));
if(p == NULL)
printf("Memory allocation failed");
else
printf("Memory allocated and initialized to zero");
- Allocates memory for an array of elements.
- All values are automatically set to zero.
3. realloc() - Reallocation of Memory
realloc() is used to resize a previously allocated
memory block without losing existing data.
Syntax
ptr = (type *) realloc(ptr, new_size);
Example
p = (int *) realloc(p, 10 * sizeof(int));
- Preserves existing data up to the minimum of old and new size.
- May move memory to a new location.
- Returns
NULLif reallocation fails.
4. free() - Deallocating Memory
free() releases dynamically allocated memory back to the system.
Syntax
free(ptr);
Example
free(p);
p = NULL;
- Prevents memory leaks.
- Accessing memory after
free()causes undefined behavior. - Setting pointer to
NULLavoids dangling pointers.
Summary
malloc()→ allocates memory (uninitialized).calloc()→ allocates and initializes memory to zero.realloc()→ resizes previously allocated memory.free()→ releases allocated memory.
Dynamic memory allocation is essential for creating flexible and memory-efficient C programs, especially when working with arrays, structures, and large data sets whose size is determined at runtime.
Dynamically Allocated Arrays
Dynamic memory allocation allows creating arrays at runtime using malloc(). A pointer returned by malloc can be indexed like an array, making it possible to form dynamically allocated arrays. This is useful when the required array size is not known before execution.
1D Dynamic Array Example
Allocating memory for a string and printing it in reverse:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(){
char *s;
int t;
s = malloc(80); // Allocate 80 bytes
if(!s){ // Check memory allocation
printf("Memory request failed\n");
exit(1);
}
gets(s); // Input string
for(t=strlen(s)-1; t>=0; t--)
putchar(s[t]); // Print reversed
free(s); // Release memory
return 0;
}
- s stores the address of allocated memory.
- Memory check is mandatory to avoid null pointer access.
- The pointer is indexed using
s[i]as a normal array.
2D Dynamic Array Example
Multi-dimensional dynamic arrays require a pointer that represents all dimensions except the first. The example below allocates memory for a 4×10 integer array and fills it with values 1 to 10 raised to the power 1-4.
#include <stdio.h>
#include <stdlib.h>
int pwr(int a,int b);
int main(){
int (*p)[10]; // Pointer to array of 10 ints
int i,j;
p = malloc(40*sizeof(int)); // Allocate 4×10 ints
if(!p){ printf("Memory failed"); exit(1);}
for(j=1;j<11;j++)
for(i=1;i<5;i++) p[i-1][j-1]=pwr(j,i);
for(j=1;j<11;j++){
for(i=1;i<5;i++) printf("%10d",p[i-1][j-1]);
printf("\n");
}
return 0;
}
int pwr(int a,int b){
int t=1;
while(b--) t=t*a;
return t;
}
Declaration insight:
int (*p)[10];
ppoints to an array of 10 integers.- It behaves like a 2D array:
p[row][column]. - Memory must be released using
free()after use.
In C++, malloc return values require typecasting:
p = (int (*)[10]) malloc(40*sizeof(int));
Dynamically allocated arrays provide flexibility in memory usage, especially when size is unknown at compile time, making them useful in data structures, file handling, and variable-sized storage.