When something is cast to void, then the value becomes NULL. However, why does a void * point to any data type? Shouldn't a void pointer just be useless?
A void pointer is a pointer to anything. It is a generic pointer that doesn't have a particular type. It can also have the value NULL in which case it doesn't point to anything.
To use a void pointer, you have to keep track of what it actually points to and when you are going to use it, you must cast it to the appropriate type.
They can be dangerous, because if you cast it to the wrong type, it will result in undefined behavior at runtime.
When something is cast to void, then the value becomes NULL.
Not true. Nothing happens to the pointed data.
Shouldn't a void pointer just be useless?
A void pointer is the closest thing C has to a "generic type" and is very useful in that it allows things like somewhat generic functions, somewhat generic containers etc.
void * is a generic object pointer. Note that there is no generic function pointer.
You can convert any object pointer value to void * and back without loss of value.
Related
I consider how should I use void * correctly (I have some break from C language). As I remember void * is used to enable passing any argument to callback function. I know that it is ok to pass something like primitive types int *, const char * or even collection of values as struct attributes *.
I consider whether passing pointer to function as void * will be ok.
ex.
typedef void (*callback_t)(void *);
typedef void (*my_custom_callback_t)( /* list of params */ )
void someAPIFunction( /*... */, callback_t callback, void *callback_param);
void standard_callback(void *param) {
((my_custom_callback_t) param) ( /* my params */ );
}
I consider whether having such types it will be correct to pass my_custom_callback as param to standard_callback?
void my_custom_callback(/* list of params */) { }
someAPIFunction( /*...*/, standard_callback, my_custom_callback);
No, you cannot pass function pointer as void *.
6.3.2.3 Pointers
A pointer to void may be converted to or from a pointer to any object type. A pointer to
any object type may be converted to a pointer to void and back again; the result shall
compare equal to the original pointer.
and
A pointer to a function of one type may be converted to a pointer to a function of another
type and back again; the result shall compare equal to the original pointer. If a converted
pointer is used to call a function whose type is not compatible with the referenced type,
the behavior is undefined.
Notice how there is no mention of possibility to mix object and function pointers. It may seem to work on some system, but it's undefined behaviour and not guaranteed to work.
However, you can create wrapper object and pass address of that:
struct wrapper {
my_custom_callback_t func;
};
struct wrapper my_wrapper = { my_custom_callback };
someAPIFunction( /*...*/, standard_callback, &my_wrapper);
Or just pass pointer to function pointer (function pointer variable is object type):
my_custom_callback_t func = my_custom_callback;
someAPIFunction( /*...*/, standard_callback, &func);
Most platforms will in fact allow you to pass a function pointer as a void *, but it's not theoretically allowed. Code might have different pointers to data. You also cannot pass a const-qualified address to a void *.
As pointed out already, this is not allowed in the general case and you will probably get a compiler warning. This is because there are platforms where function pointers are larger than data pointers.
The much more common case however is that the pointer sizes are indeed equal. Interfaces for accessing shared objects like dlsym() or GetProcAddress() actually rely on that.
So if you are sure that all your target platforms will use the same size for function pointers as for data pointers, you can make it explicit (so the compiler doesn't issue any warnings) by first casting to e.g. uintptr_t. The cast to and from an integer is allowed for all pointer types, and as long as the integer is large enough to hold the pointer, well-defined. uintptr_t is guaranteed to be large enough for a data pointer, so if the function pointer is the same size, it's fine.
I have a question regarding the void pointer in c language. I would like to know Can we dereference a void pointer without knowing its type?
No, because you don't know how to interpret the data contained by the corresponding memory space. Memory itself has no type, and it is pointers that contains the type information. For example, memory pointed to by int * is interpreted as an int.
When dereferencing a void *, there is no way for the compiler to tell which type bytes starting from that address should be interpreted as. It can be a double, an unsigned long, or even an array of chars.
However, it is possible to get dereference a void * through casting, because the cast operator contains the information about object type.
No, A void pointer can be dereferenced only after explicit casting. For example:
int a = 5;
void *b = &a;
printf(“%d\n”, *((int*)b));
TL;DR No, you can't.
While dereferencing a pointer-to-type, you generate an "object" of the type.
Since a void is not a complete type, you cannot dereference a void* directly. That is why, you need to either
copy the pointer to another pointer of a complete type
cast the pointer to another complete type
and then, you can dereference to get the object of the new complete type.
You cannot. Dereferencing a void pointer requires an explicit cast beforehand.
You can ofcourse cast it to any particular type and then dereference it without knowing its original type, but why you would want to do that is beyond me.
Knowing more C++ than C I wondered if someone could explain the reason why malloc() always returns a pointer of type void, rather than malloc having been implemented with some mechanism which allows it to return a pointer of the type the user passed in? It just seems a little "hacky" constantly explicitly casting the returned void pointer to the type you want.
Well, in C you don't have to do the cast, so your point is moot. That is, these two statements are 100% equivalent:
char *x = malloc(100);
char *y = (char *)malloc(100);
Conversions to and from void * are implicit in C. So, to address your question, the very reason malloc returns void * is so that you don't have to cast.
Besides that, in C there's no way to pass type information around, so doing something like:
char *x = malloc(100, char);
is not possible.
If you're in C++, the cast is necessary, but you shouldn't be using malloc anyway - that's what new is for, and it does handle the type information correctly.
It's not hacky at all, from C standard ISO/IEC 9899 2011, section 6.2.2.3:
A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
So a pointer to void* is a valid pointer to whatever type you want without the need of explicit casting.
In addition to this you can't dynamically pass a type to a function to let so that it will return the correct type, you can pass just the size itself (so malloc would be able to allocate size_t count * size_t size but not return the correctly type in any case).
C has no mechanism for "passing a type" at all. Also, in C, conversion from void* to a pointer of any other type is automatic (no cast is needed) so malloc works naturally in C. It's only in C++ where malloc requires casts to work.
There are two reasons, first, malloc doesn't know why you need memory. So it just return number of bytes asked to return. Secondly you cannot de-reference void * easily so it can help you to avoid accidents.
int *p;
p = (int *)malloc(sizeof(int)*10);
I've come across this piece of code in my O.S book:
void *foo()
{
// does something
pthread_exit(NULL);
}
What is the meaning of void *foo?
Does that mean the function return a pointer to something of type void?
No, it means that the function returns an pointer of the untyped type - void*.
This is a "generic" pointer type. Any pointer to data can be cast to void*, and returned back to the caller. However, in order to dereference the pointer, you must cast it to a non-void pointer type (int*, long*, char*, and so on).
void * means it returns a pointer to some type, it isn't specified which. In order to be used the pointer is casted to the appropriate type and then used. The fact that void *foo is just a matter of spacing.
Check out this explanation
ive seen functions passing pointers in their parameters and they are common in dynamic use executing different functions after afew steps. However i came across this representation in a header file:
void *allocate_mem(u_int32_t n);
Any clue to how it is to be used? Is the function a pointer or does it return a pointer?
See my comments.
Please use cdecl.org whenever you have questions like this... entering void *allocate_mem(u_int32_t), we get the following.
declare allocate_mem as function (u_int32_t) returning pointer to void.
So, we know allocate_mem returns void *. Now, you're probably wondering why you would ever want a pointer to void...
§6.3.2.3.1 of the C99 standard states as follows.
A pointer to void may be converted to or from a pointer to any incomplete or object type. A pointer to any incomplete or object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
Thus you can convert the result of allocate_mem to fit your needs, e.g.
float *data = allocate_mem(1024 * sizeof(float))
The function returns a pointer to the new memory allocated.
The return type is a void*, the reason being that the function doesn't know what you want to use it for.
If you want to use it as an array of integers, you would cast it to an int*
eg.
int *p = allocate_mem(4*10);
The argument is the size (bytes) of memory that needs to be allocated. Therefore, allocating 40 bytes for 4-byte integers makes an array of ten 4-byte integers.
A void * is a pointer to something. What it points to is not known, but the idea is for it to work as sort of a neutral pointer. A void* param can take any kind of pointer type. However great care needs to be taken while handling these pointers as they come with their own set of limitations. You cannot dereference a void* it has to be cast to a valid type. The same goes with applying pointer arithmetic.
Refer this discussion for more details - C - pointers in functions and void variable type?