<span>void</span> and <span>void*</span> are fundamental yet very useful types in C programming, especially when dealing with generic pointers (such as <span>malloc</span>, callback functions, etc.), where <span>void*</span> is crucial.
1. What are <span>void</span> and <span>void*</span>
| Syntax | Meaning |
|---|---|
<span>void</span> |
Indicates “no type” or “no return value”, commonly used for function return types |
<span>void*</span> |
Generic pointer type, can point to any type of data |
2. Usage of <span>void</span>
1. Indicates a function with “no return value”
void say_hello() {
printf("Hello!\n");
}
2. Indicates a function that “takes no parameters” (old style)
void do_nothing(void) {
// Function takes 0 parameters (explicitly stated)
}
3. Usage of <span>void*</span>: Generic pointer type
✨ 1. <span>malloc</span> returns a <span>void*</span>
int* p = (int*)malloc(sizeof(int) * 5);
<span>malloc</span>returns a<span>void*</span>, you need to manually cast it to the target type pointer- In C++, casting is mandatory, while in C it can be omitted, but it’s recommended to be explicit
✨ 2. Function parameter passing (generic parameters)
void print_value(void* data, char type) {
if (type == 'i') {
printf("int: %d\n", *(int*)data);
} else if (type == 'f') {
printf("float: %f\n", *(float*)data);
}
}
Call:
int x = 10;
float y = 3.14;
print_value(&x, 'i');
print_value(&y, 'f');
✨ 3. Used with thread libraries (e.g., <span>pthread</span>)
void* thread_func(void* arg) {
int* p = (int*)arg;
printf("Thread got: %d\n", *p);
return NULL;
}
✨ 4. Implementing generic containers (e.g., linked lists, stacks, queues)
typedef struct Node {
void* data;
struct Node* next;
} Node;
You can store any type of data, as long as you correctly cast the type when accessing it.
4. void* requires explicit type casting
Because <span>void*</span> has no type information, it cannot be dereferenced directly.
void* p;
int x = 10;
p = &x;
printf("%d\n", *(int*)p); // ✅ OK
// printf("%d\n", *p); // ❌ Error: cannot dereference void*
5. Limitations of void*
| Limitation | Explanation |
|---|---|
Cannot directly dereference <span>*p</span> |
Because <span>void</span> is an incomplete type, size is unknown |
Cannot perform <span>p++</span> operation |
Same reason: cannot know how many bytes to skip |
| Must explicitly cast back to target type pointer | Otherwise, the compiler does not know what type of data you are operating on |
6. Complete example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_any(void* data, char type) {
switch (type) {
case'i':
printf("int: %d\n", *(int*)data);
break;
case'd':
printf("double: %f\n", *(double*)data);
break;
case's':
printf("string: %s\n", (char*)data);
break;
}
}
int main() {
int x = 42;
double y = 3.14;
char* msg = "hello";
print_any(&x, 'i');
print_any(&y, 'd');
print_any(msg, 's');
return 0;
}
7. Summary Comparison
| Type | Meaning | Example |
|---|---|---|
<span>void</span> |
No return value/parameters | <span>void func(void)</span> |
<span>void*</span> |
Pointer to any type | <span>void* ptr = malloc(10);</span> |
Review of Uses
<span>malloc/free</span>and other memory function return values- Generic parameter passing (e.g., callback functions)
- Implementing data structures (linked lists/queues, etc.)
- Used with
<span>pthread</span>,<span>qsort</span>and other library functions