Why Void Pointers Matter in C: Flexibility and Generic Programming
The article explains that the C language’s void* type serves as a universal pointer, detailing its strong versatility, role as a common interface for memory‑management functions, foundation for generic programming, support for object‑oriented patterns, and usage considerations such as required casting, inability to dereference directly, and type‑safety trade‑offs.
Introduction
In C, void* is a generic pointer that can hold the address of any object type. It is used for generic programming, memory‑management interfaces, and opaque data structures.
Key Advantages
1. Strong Generality
A void* can store the address of any data type.
int a = 10;
float b = 3.14f;
char c = 'X';
void *ptr;
ptr = &a; // points to int
ptr = &b; // points to float
ptr = &c; // points to char2. Unified Memory‑Management Interface
Standard allocation functions use void* for parameters and return values.
void* malloc(size_t size);
void* calloc(size_t num, size_t size);
void* realloc(void *ptr, size_t size);
void free(void *ptr);
int *int_arr = (int*)malloc(10 * sizeof(int));
double *dbl_arr = (double*)malloc(20 * sizeof(double));3. Basis for Generic Algorithms
Functions such as qsort accept void* to operate on arbitrary arrays.
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));4. Memory‑Operation Functions
Functions like memcpy, memset, and memcmp work with void*.
void *memcpy(void *dest, const void *src, size_t n);
void *memset(void *s, int c, size_t n);
int memcmp(const void *s1, const void *s2, size_t n);5. Simulating Object‑Oriented Patterns
Structures can store a void* for opaque data and function pointers for methods.
typedef struct {
void *data;
void (*print)(void *);
} Object;
void print_int(void *data) {
printf("%d
", *(int*)data);
}
void print_float(void *data) {
printf("%f
", *(float*)data);
}6. Information Hiding
Opaque types hide implementation details by exposing only a void* handle.
// Header
typedef void* Database;
Database create_db(void);
void store_data(Database db, void *data, size_t size);
// Implementation
struct RealDatabase { /* hidden fields */ };
Database create_db(void) {
return (Database)malloc(sizeof(struct RealDatabase));
}Typical Applications
1. Generic Data Structures
typedef struct {
void **items;
size_t size;
size_t capacity;
} GenericArray;
void init_array(GenericArray *arr, size_t initial_capacity) {
arr->items = malloc(initial_capacity * sizeof(void*));
arr->size = 0;
arr->capacity = initial_capacity;
}
void push_back(GenericArray *arr, void *item) {
if (arr->size >= arr->capacity) {
arr->capacity *= 2;
arr->items = realloc(arr->items, arr->capacity * sizeof(void*));
}
arr->items[arr->size++] = item;
}2. Thread Argument Passing
#include <pthread.h>
struct ThreadData {
int id;
char *message;
};
void* thread_func(void *arg) {
struct ThreadData *data = (struct ThreadData*)arg;
printf("Thread %d: %s
", data->id, data->message);
return NULL;
}
int main(void) {
pthread_t thread;
struct ThreadData data = {1, "Hello from thread"};
pthread_create(&thread, NULL, thread_func, (void*)&data);
pthread_join(thread, NULL);
return 0;
}3. Callback User Data
typedef void (*Callback)(void *user_data);
void process_data(int *data, size_t size, Callback cb, void *user_data) {
if (cb) {
cb(user_data);
}
}
void print_completion(void *user_data) {
printf("Processing completed by %s
", (char*)user_data);
}
int main(void) {
int data[100];
process_data(data, 100, print_completion, "Main thread");
return 0;
}Precautions
Explicit casting required : Convert a void* to the target type before dereferencing.
Cannot dereference directly : *void_ptr is illegal.
No pointer arithmetic : Arithmetic on void* is undefined.
Type‑safety trade‑off : Overuse can reduce compile‑time safety.
Conclusion
void*provides a powerful, flexible mechanism for generic code, memory management, and abstraction in C. When used judiciously, it enables reusable components while acknowledging the loss of some type safety.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
