I wrote these lines of code expecting them to work just fine but I keep getting an error that says "invalid use of void expression" and I have no clue why
int main(){
int a=12;
void* ptr = &a;
printf("%d",*ptr);
}
I thought void pointers can point to any type of data so what's the issue here? I even tried to cast the void pointer to an integer pointer but I still get the same error.
I thought void pointers can point to any type of data so what's the issue here.
A void * can point to any type of data1. But it only remembers the address, not the type. To use it with *, you must tell the compiler what type to use:
int a = 12;
void *ptr = &a;
printf("%d\n", * (int *) ptr); // Use cast to specify type.
During execution, the program will not remember that ptr was assigned an address from an int and automatically know to load an int in the printf call. During compilation, the compiler will not remember this either. To use the pointer to access data, you must convert it back to an appropriate type, then use that.
Footnote
1 A pointer should retain all the qualifiers of any object it is set to point to. A pointer to a const int x or volatile int x ought to be assigned to a const void *p or a volatile void *p, respectively, not a void *p without the qualifiers.
You can not dereference a void pointer, the underlying type (void) is incomplete.
You should either use a different type for your pointer (such as int*) or you should cast your void pointer to a complete type (again, probably int*).
You can't dereference a void*, as you've seen, but casting it to an int* most definitely works:
printf("%d",*(int*)ptr);
OnlineGDB demo
Related
This works :
int main(){
char *pc[2]={"Hello","Welcome"};
void *p=pc;
char **pt=p;
printf("%s\n",*pt);//Output : Hello
return 0;
}
However this doesn't work :
void test(void *p[]){
char **pt=p;
printf("%s\n",*pt);
};
int main(){
char *pc[2]={"Hello","Welcome"};
void *p=pc;
test(p);
return 0;
}
I get the error :
incompatible pointer types initializing 'char **' with an expression of type 'void **'
Notice also how changing void *p[] to void *p makes it work :
void test(void *p){
char **pt=p;
printf("%s\n",*pt);
};
int main(){
char *pc[2]={"Hello","Welcome"};
void *p=pc;
test(p); //Output : Hello
return 0;
}
Could someone give an explanation of how void pointers really works ?
What's the purpose of giving the function test() void *p[] instead of void *p? Can't we simply assign void *p for every data types ?
Does the compiler make a distinction between void *p and void *p[]?
Could someone give an explanation of how void pointers really works?
void* is the generic object pointer type in C. Not to be mixed up with function pointers, which are not compatible. void pointer conversions are described in the C standard C17 6.3.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 you can assign any object pointer to a void pointer and vice versa.
However, this special rule only applies to void*, it does not apply recursively to void**. A void** is actually just a plain pointer to object type, it doesn't have any of the special conversion rules above (unless you de-reference it). That void** is a generic pointer is a common misconception.
(So common that it even infamously made it into the CUDA API, which was a library design bug - calling this with for example char** as parameter is a C language constraint violation.)
Furthermore, any type qualifiers (const, volatile) need to be respected:
void* v;
const void* cv=v; // ok
v = cv; // not ok
int* i;
v = i; // ok
cv = i; // ok
i = v; // ok;
i = cv; // not ok
Formally this is stated in the rules of the assignment operators, C17 6.5.16.1:
the left operand has atomic, qualified, or unqualified pointer type, and (considering
the type the left operand would have after lvalue conversion) one operand is a pointer
to an object type, and the other is a pointer to a qualified or unqualified version of
void, and the type pointed to by the left has all the qualifiers of the type pointed to
by the right;
What's the purpose of giving the function test() void *p[] instead of void *p? Can't we simply assign void *p for every data types ?
There is no apparent reason to do that unless you for example expect to return a void pointer through the parameter:
void my_malloc(void** ptr)
{
*ptr = malloc(123);
}
Alternatively you might want to use void** in order to pass an array of void pointers to a function. You could also use a void* for that, but it's a bit strange. Note for example that C standard lib function bsearch has this API:
void *bsearch(const void *key, const void *base, ...
We can pass a base array to this function where the array is an array of pointers, strings for example. As long as we are using some manner of object pointer and converting it to a void pointer, anything goes.
Does the compiler make a distinction between void *p and void *p[]?
Yes, as explained above they are different types. A void *p[] array when part of a function parameter list "decays" like any array into a void**.
I have 2 questions about pointers in c.
1) from my understanding the & returns the memory address of a variable. For example:
int x=10;
int *p=&x;
So I think that the & will return the memory address of x and that memory address is type int* because the variable type of x is int.
Also because the type of the address is int* I believe that is the reason that only an int* (and void *) pointer can point in the address (they are the same type).
Any thoughts about that? comments? I don't know if I am correct.
2) It's about the void pointer. I know that the void* pointer can point to any type of variable. For example
int x=10;
void *ptr=&x;
Now I have a function:
void * foo(some parameters)
{
// just for this example let's say that I return the address of a local variable
// I know that is wrong to do so because when the foo ends
// the local variables deallocate
int k=10;
void *ptr=&k;
return ptr;
}
So my pointer is type void but it points to int* memory address. So ptr will save the address of k and when I return ptr the address of k is returned which is type int* . But my function is type void*.
What is happening here?
According to the C Standard (6.3.2.3 Pointers)
1 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 for example in this code snippet
int x = 10;
void *p = &x;
the expression &x in the right side of the assignment has the type int *. According to the quote it may be converted to pointer of the type void * in the left side of the assignment.
1) Yes all of that is correct.
2) The type of the pointed-at data remains int no matter what kind of pointer that points at it. (This is known as effective type in formal C.) In your example you return a void pointer so that's the type the caller gets. The information of what type it pointed at is lost, from the point you do void *ptr=&k; and onward. This is why void pointers are problematic to use.
1) You are correct
2) It is simply returning a void * that is pointing to k - a local variable. (Any pointers can be cast to void pointers).
You are correct in saying that you should not use the returned value as k no longer exists
I have similar "generic" procedure like qsort, which has a void pointer (pointing at an array) and also a function pointer parameter. This function should work on any type of array.
Example:
void do_something(void * array, int count, int size, void (*test)(const void*)){
int i;
for(i=0; i<count; i++){
test(array + (index * size));
}
}
This however gives me the following warning (gcc test.c -pedantic-errors):
error: pointer of type ‘void *’ used in arithmetic [-Wpedantic]
And after some research I found out it's a bad practice to use void pointers like this. (E.g. Pointer arithmetic for void pointer in C)
So how does the standard library do this kind of stuff for like qsort? Looking at this code: (http://aturing.umcs.maine.edu/~sudarshan.chawathe/200801/capstone/n/qsort.c), I see the following:
void
_quicksort (void *const pbase, size_t total_elems, size_t size,
__compar_fn_t cmp)
{
register char *base_ptr = (char *) pbase;
....
char *lo = base_ptr;
char *hi = &lo[size * (total_elems - 1)];
...
}
Are they casting to (char *) regardless of the actual type?
i asked similar question Can I do arithmetic on void * pointers in C?.
Void * arithmetic is not defined. What does it mean to add 1 to a void pointer ? Most compilers (if they allow it) treat it as incrementing by sizeof(char) ("the next byte") but warn you.
So the right thing to do is to explicitly make it do what you want -> cast to char* and increment that
Pointer arithmetic on incomplete data type void is not legal and that is what the compiler is complaining.
As you can see in the _quicksort() the pointer is a constant one so that you can't modify the address the pointer is pointing to. There is no arthmetic operation happening on the void pointer.
Making a pointer void just takes away the "context" of the pointer - That is, how the system should look at the pointer or whatever the pointer is holding.
For this reason, compilers do not do arithmetic on void pointers. In order to do pointer arithmetic, the compiler needs to know the type of the pointer such that it can do the proper conversions (if the pointer holds an int, it will not do an addition of with 32 bits or at least it will let you know something is gone awry!).
For this reason, the only way to do this is to cast the pointer to something and do it - I would not recommend it unless you know very well what the pointer is getting. Void pointers are rather very dark programming.
I found this function definition
void *func(void *param) {
}
Actually, I have a certain confusion regarding this function definition. What does void * mean in the return type of the function as well as the argument. I am a beginner in C. So please don't mind. Thank you
void *func(void *param) {
int s = (int)param;
....
}
Well looking at the above program which I found. I think it should have been
int *s = (int *)param;
isn't it? I am confused
void * means it's a pointer of no specific type, think of it as a generic pointer, unlike say int * an int pointer.
You can cast it into a different type if need be (for instance if you are going to do pointer arithmetic with the pointer).
You might find this SO question of use: Concept of void pointer in C programming
It simply means that the function func takes one parameter which is a pointer (to anything) and returns a pointer (to anything). When you use a void *, you are telling the compiler "this is a pointer, but it doesn't matter at this point what it's a pointer to".
When you want to actually use the data it's pointing to, you need to cast it to a pointer to some other type. For example, if it points to an int, you can create an int * variable and dereference that:
int *int_ptr = (int *)param;
// now (*int_ptr) is the value param is pointing to
you can think of it as a raw pointer, nothing more than an address, think about it, pointers are nothing more than address right, so they should all be of equal size, either 32 or 64 bits in most modern systems but if thats the case why do we say int * or char * or so on if they are all the same size, well thats because we need of a way to interpret the type we are pointing to, int * means when we dereference go to that address and interpret the 4 bytes as an int or char * means when we dereference go to that address and get a byte, so what happens when you dereference a void * well you get warning: dereferencing ‘void *’ pointer basically we really can't and if you do its affects are compiler dependent, the same applies when we do arithmetics on it.
So why bother using them? well I personally don't and some groups dont particularly like them, fundamentally they allow you to create fairly generic subroutines, a good example would be memset which sets a block of memory to a certain byte value, its first argument is a void * so it won't complain whether giving a char * or int * due note that it works on a per byte basis, and you need to properly calculate the total size of the array.
void *func(void *param) {
}
param is a void pointer means it is a pointer of any reference type. since a void pointer has no object type,it cannot be dereferenced unless it is case.
so void *param;
int *s=(int*)param;
here since param is an pointer variable so you will have to cast it as a pointer variable.not to a int type as you did there.
e.g.
int x;
float r;
void *p=&x;
int main()
{
*(int *)p=2;
p=&r;
*(float*)p=1.1;
}
in this example p is a void pointer. now in main method I have cast the p as a int pointer and then as a float pointer so that it can reference to first a integer and then a float.
Returning a pointer of any type. It can be of any datatype.
Is it safe to convert an int pointer to void pointer and then back to int pointer?
main()
{
...
int *a = malloc(sizeof(int));
...
*a=10;
func(a);
...
}
void func(void *v)
{
int x=*(int *)v;
...
}
Is this a valid way of getting the integer value back in the function?
Yes, it is safe. The Standard says so (6.3.2.3/1)
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.
It is "safe" insofar as the pointer resulting from the int => void => int conversion will be the same as the original pointer.
It is not "safe" insofar as it's easy to get wrong and you have to be careful (that said, this type of code is often necessary in C, since void* is often used as a form of generalization).