Are void * pointers meant for generic typing in C? - Stack Overflow
Concept of void pointer in C programming - Stack Overflow
c - What does void* mean and how to use it? - Stack Overflow
void pointers in generic linked list
Videos
The purpose of a void * is to provide a welcome exception to some of C's typing rules. With the exception of void *, you cannot assign a pointer value of one type to an object of a different pointer type without a cast - for example, you cannot write
int p = 10;
double *q = &p; // BZZT - cannot assign an int * value to a double *
When assigning to pointers of different types, you have to explicitly cast to the target type:
int p = 10;
double *q = (double *) &p; // convert the pointer to p to the right type before assigning to q
except for a void *:
int p = 10;
void *q = &p; // no cast required here.
In the old days of K&R C, char * was used as a "generic" pointer type1 - the memory allocation functions malloc/calloc/realloc all returned char *, the callback functions for qsort and bsearch took char * arguments, etc., but because you couldn't directly assign different pointer types, you had to add an explicit cast (if the target wasn't a char *, anyway):
int *mem = (int *) malloc( N * sizeof *mem );
Using explicit casts everywhere was a bit painful.
The 1989/1990 standard (C89/C90) introduced the void data type - it's a data type that cannot store any values. An expression of type void is evaluated only for its side effects (if any)2. A special rule was created for the void * type such that a value of that type can be assigned to/from any other pointer type without need of an explicit cast, which made it the new "generic" pointer type. malloc/calloc/realloc were all changed to return void *, qsort and bsearch callbacks now take void * arguments instead of char *, and now things are a bit cleaner:
int *mem = malloc( sizeof *mem * N );
You cannot dereference a void * - in our example above, where q has type void *, we cannot get at the value of p without a cast:
printf( "p = %d\n", *(int *)q );
Note that C++ is different in this regard - C++ does not treat void * specially, and requires an explicit cast to assign to different pointer types. That's because C++ provides overloading mechanisms that C doesn't.
- Every object type should be mappable to an array of
char. - In K&R C, all functions had to return a value - if you didn't explicitly type the function, the compiler assumed it returned
int. This made it difficult to determine which functions were actually meant to return a value vs. functions that only had side effects. Thevoidtype was handy for typing functions that weren't meant to return a value.
C suffers from the absence of function overloading. So most C "generic" functions as for example qsort or bsearch use pointers to void * that to be able to deal with objects of different types.
In C you need not to cast a pointer of any type to a pointer of the type void *. And a pointer of any type can be assigned with a pointer of the type void * without casting.
So in C the functions from your code snippet can be rewritten like
void store(struct GenericStruct *strct, int *myarr){
strct->ptr = myarr;
}
int *load(struct GenericStruct *strct){
return strct->ptr;
}
Is it possible to dereference the void pointer without type-casting in C programming language...
No, void indicates the absence of type, it is not something you can dereference or assign to.
is there is any way of generalizing a function which can receive pointer and store it in void pointer and by using that void pointer we can make a generalized function..
You cannot just dereference it in a portable way, as it may not be properly aligned. It may be an issue on some architectures like ARM, where pointer to a data type must be aligned at boundary of the size of data type (e.g. pointer to 32-bit integer must be aligned at 4-byte boundary to be dereferenced).
For example, reading uint16_t from void*:
/* may receive wrong value if ptr is not 2-byte aligned */
uint16_t value = *(uint16_t*)ptr;
/* portable way of reading a little-endian value */
uint16_t value = *(uint8_t*)ptr
| ((*((uint8_t*)ptr+1))<<8);
Also, is pointer arithmetic with void pointers possible...
Pointer arithmetic is not possible on pointers of void due to lack of concrete value underneath the pointer and hence the size.
void* p = ...
void *p2 = p + 1; /* what exactly is the size of void?? */
In C, a void * can be converted to a pointer to an object of a different type without an explicit cast:
void abc(void *a, int b)
{
int *test = a;
/* ... */
This doesn't help with writing your function in a more generic way, though.
You can't dereference a void * with converting it to a different pointer type as dereferencing a pointer is obtaining the value of the pointed-to object. A naked void is not a valid type so derefencing a void * is not possible.
Pointer arithmetic is about changing pointer values by multiples of the sizeof the pointed-to objects. Again, because void is not a true type, sizeof(void) has no meaning so pointer arithmetic is not valid on void *. (Some implementations allow it, using the equivalent pointer arithmetic for char *.)
A pointer to void is a "generic" pointer type. A void * can be converted to any other pointer type without an explicit cast. You cannot dereference a void * or do pointer arithmetic with it; you must convert it to a pointer to a complete data type first.
void * is often used in places where you need to be able to work with different pointer types in the same code. One commonly cited example is the library function qsort:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
base is the address of an array, nmemb is the number of elements in the array, size is the size of each element, and compar is a pointer to a function that compares two elements of the array. It gets called like so:
int iArr[10];
double dArr[30];
long lArr[50];
...
qsort(iArr, sizeof iArr/sizeof iArr[0], sizeof iArr[0], compareInt);
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareDouble);
qsort(lArr, sizeof lArr/sizeof lArr[0], sizeof lArr[0], compareLong);
The array expressions iArr, dArr, and lArr are implicitly converted from array types to pointer types in the function call, and each is implicitly converted from "pointer to int/double/long" to "pointer to void".
The comparison functions would look something like:
int compareInt(const void *lhs, const void *rhs)
{
const int *x = lhs; // convert void * to int * by assignment
const int *y = rhs;
if (*x > *y) return 1;
if (*x == *y) return 0;
return -1;
}
By accepting void *, qsort can work with arrays of any type.
The disadvantage of using void * is that you throw type safety out the window and into oncoming traffic. There's nothing to protect you from using the wrong comparison routine:
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareInt);
compareInt is expecting its arguments to be pointing to ints, but is actually working with doubles. There's no way to catch this problem at compile time; you'll just wind up with a missorted array.
Using a void * means that the function can take a pointer that doesn't need to be a specific type. For example, in socket functions, you have
send(void * pData, int nLength)
this means you can call it in many ways, for example
char * data = "blah";
send(data, strlen(data));
POINT p;
p.x = 1;
p.y = 2;
send(&p, sizeof(POINT));