I have to use void** in a program. I am writing the following code. please guide me where I am wrong.
struct kdnode
{
kdnode* lch;
int k;
void **dataptr;
kdnode* rch;
};
then I am assigning
kdnode rt;
rt.dataptr=new void*[k];
rt.dataptr[0]=new int;
there was also this dereferencing involved:
*(rt->dataptr[0])=n; //n is an initialized integer value.
basically I want to assign the elements of the array of void pointers to pointers of different datatypes. As the compiler is throwing error :
void* is not a pointer-to object type
Please guide me what to do.
I can reproduce this error only if I add something like
*rt.dataptr[0] = 1;
With the addition, g++ complains:
main.cpp:13:14: error: ‘void*’ is not a pointer-to-object type
*rt.dataptr[0] = 1;
You can't dereference a void *. Cast it back to the original type (int * in this case) if you want to dereference it.
Related
I found out that using a C compiler the code below works but not with a C++ compiler. I understand that casting to void** is the correct usage but I can't understand why it compiles with the C compiler even if I use the void* (commented out).
#include <stdio.h>
int fn(void **arg)
{
int *pvalue = *(int**)arg;
*pvalue = 200;
return 0;
}
int main()
{
int value = 99;
int *pvalue = &value;
// fn((void *)&pvalue); // works only in C
// error C2664: 'int fn(void **)': cannot convert argument 1 from 'void *' to 'void **'
fn((void **)&pvalue); // correct, works for both C/C++
printf("%d", value);
return 0;
}
Can someone explain why this is the case?
In C there is allowed to assign a pointer of the type void * to a pointer of other type. This takes place in this call
fn((void *)&pvalue)
where the argument has the type void * that is assigned to the function parameter that has the type void **.
int fn(void **arg)
{
int *pvalue = *(int**)arg;
*pvalue = 200;
return 0;
}
However such an assignment in general is unsafe. For example the value of a pointer of the type void * can not be properly aligned to be assigned to a pointer of other type.
So it was decided to not allow such an assignment in C++ to make programs more safer.
I can't understand why it compiles with the C compiler even if I use the void* (commented out).
It compiles because void* is implicitly convertible to other pointers in C.
fn((void **)&pvalue); // correct, works for both C/C++
This may be well-formed because of the cast, the standard doesn't technically give explicit guarantee that conversion to void** and back yields the same address.
While this may be likely to work in practice, there is no reason to not use void* as the function argument instead, which does have the guarantee. As a bonus, you won't need the cast in the call. Like this:
int fn(void *arg);
fn(&pvalue); // correct, works for both C/C++
Of course, this is assuming type erasure is needed in the first place. Avoid void* when it is not needed.
For avoidance of doubt, there is nothing correct in
fn((void **)&pvalue);
It is just as incorrect as
fn((void *)&pvalue);
The correct way to use the API is to do
int fn(void **arg)
{
int *pvalue = (int *)*arg;
*(int *)pvalue = 200;
return 0;
}
or
int fn(void **arg)
{
*(int *)*arg = 200;
return 0;
}
with
int main()
{
int value = 99;
void *pvalue = (void*)&value;
fn(&pvalue);
printf("%d", value);
return 0;
}
You're not allowed to access an object using any other pointer type, other than the declared type, compatible type, or a character type. Furthermore, while void * is used as a generic pointer type to all sorts of objects in C, there is no generic pointer to a pointer type in C - other than void *!
And this is the reason why the void ** is almost always a sign of a design error in APIs - most usages are just wrong.
I have a very simple method with the following prototype:
void *station_0(void* p1);
I am calling it like this:
product_record r;
pthread_create(thread, NULL, station_0, (void *)&r);
Inside this method all I need to do is cast p1 to an already defined struct product_record, I am currently trying this inside of my method:
product_record p = (product_record)p1
but the compiler complains on that line(above) saying error: invalid conversion from 'void*' to 'int' [-fpermissive]
I don't think I understand this warning at all. Why cannot I simply cast a void* to my struct?
You need two steps - convert the void pointer to a product_record pointer and then de-reference that. This can be done in the line
product_record p = *(static_cast<product_record *>(p1));
Here's my code:
#include <iostream>
using namespace std;
int main()
{
void *x;
int arr[10];
x = arr;
*x = 23; //This is where I get the error
}
As you can see, the code is very simple. It just creates a void pointer x which points to the memory address of the array 'arr' and puts the integer 23 into that memory address. But when I compile it, I get the error message "'void*' is not a pointer-to-object type". When I use an 'int' pointer instead of a void pointer and then compile it, I don't get any errors or warnings. I wanna know why I get this error.
Thank you.
As the compiler message says, void* is not a pointer to object type. What this means is that you cannot do anything with void*, besides explicitly converting it back to another pointer type. A void* represents an address, but it doesn’t specify the type of things it points to, and at a consequence you cannot operate on it.
The compiler needs the type of the variable to to dereference the pointer.
only example no malloc:
*int myPtnr = 0x12345;
When you write
*myPtr = NUMBER:
The compiler looks at the type and say .. okay here we have a int ... the Information i need are in the next 4 bytes starting with the adress of the pointer.
Thats the reason why you have to tell the compiler the type. When you use void the compiler dont know how much bytes he has to use for dereference.
you cant derefrence void*, and that is what the coder is doing.
*x = 23; // this cant be done with void*
instead :
x = &arr[index] ; // this is correct
struct limit{
int up;
int down;
};
void *x;
struct limit *l;
l->up=1;
l->down=20;
x=l;
cout<<x->up;
This is part of my code I am getting error in last line ‘void*’ is not a pointer-to-object type. I know last line in my code is wrong. I just want to know how to print up and down values using x variable.
In this part:
struct limit *l;
l->up=1;
l->down=20;
you are dereferencing uninitialized pointer l, which results in undefined behavior. However, even if you initialized it properly, after you assign it to void*, you can not dereference void pointer:
void* x = l;
cout<< x->up;
you need to explicitly cast it back to struct limit*:
void* x = l;
struct limit * y = static_cast<struct limit*>(x);
cout << y->up;
or yet even better: avoid using void* at first place.
Since you mentioned that you're doing this because of pthreads, then this answer will help you :)
If I do the following all is ok:
char* cp = "abc";
void* vp = NULL;
vp = static_cast<void*>(cp);//ok
cp = static_cast<char*>(vp);//ok
But the following is not:
char** cpp = &cp;
void** vpp = NULL;
vpp = static_cast<void**>(cpp);//error C2440: 'static_cast':
//cannot convert from 'char **' to 'void **'
cpp = static_cast<char**>(vpp);//error C2440: 'static_cast':
//cannot convert from 'void **' to 'char **'
Please can someone explain to me why the second examples are not allowed. Please don't quote the C++ standard as your whole answer, because I've already seen answers that quote it, and I don't understand what they meant. I want to understand why the second examples don't work (ie. if you could give an example where it would be dangerous that would be a great help). Because I don't get it. To me, both examples are casting pointers. Why does an additional level of indirection make any difference?
A void * pointer can point at "anything", and it is valid to convert all pointers to a void *, and it is valid to convert all pointers from void * to some other type.
However, a void ** is a pointer that points to a void * value. And a char ** is a pointer that points to char * value. These types don't point to the types that are convertible from one another. You can, if you NEED to do this, use void **vpp = reinterpret_cast<void **>(cpp);, but it's "not safe" (you are basically telling the compiler "Look, I know what I'm doing here, so just do it", which may not do what you actually expected...)
The restriction is to avoid breaking the type system. The first conversion is fine:
type *p = ...;
void *vp = p;
While you are giving away the type, you cannot inflict too much damage to the original value without since there is little to be done with a void object and all changes to vp are local to the pointer and cannot affect p.
If the second case was allowed:
type **p = ...;
void **vp = p;
Then perfectly looking and correct code could break your application. For example:
int *parray[10];
int **p = parray;
void **vp = p;
*vp = new double(); // now parray[0] is a pointer to a double object,
// not a pointer to an int!!!
The type system has been subverted.
That is, the problem is that in the second case there are operations that can be applied to the destination pointer that can modify the original object and cause bugs. Similar examples can be found with const other cases (you can convert int* to const int*, but you cannot convert int** to const int**...).