How to cast a pointer in C++

23,596

Solution 1

(void*) is not an lvalue, it is kind of a casting operator, you need to have the ampersand to the immediate left of the variable (lvalue). This should be right:

foo(((void**)&IntPtr));

Solution 2

void foo(void **Pointer);

int main ()
{
    int *IntPtr;

    foo((void**)&IntPtr);
}

Solution 3

When you do

(void*)IntPtr

you create a temporary variable, which is only an rvalue, and so can't be dereferenced.

What you need to do is:

int main()
{
  int* IntPtr;
  void* VoidPtr = (void*)IntPtr;
  foo(&VoidPtr);
}

or equivalent

Solution 4

More C++ style:

foo( reinterpret_cast< void** >( IntPtr ) );

But remember, according to Standard such a cast is implementation specific. Standard gives no guarantees about behavior of such cast.

Solution 5

As others point out, you have the order of the cast and the & wrong. But why do you use void** at all? That means that you accept a pointer to a void pointer. But that's not at all what you want. Just make the parameter a void*, and it will accept any pointer to some object:

void foo(void*);

int main () {
    int *IntPtr;
    foo(&IntPtr);
    assert(IntPtr == NULL);
}

That's what void* is for. Later, cast it back using static_cast. That's a quite restrictive cast, that doesn't allow dangerous variants, unlike the C style cast (type):

void foo(void* p) {
    int** pint = static_cast<int**>(p);
    *pint = NULL;
}

If the function takes pointers to void*, then that function can't accept pointers to int*. But if the function accepts either or, then the function should accept void*, and you should cast to the proper type inside the function. Maybe paste what you really want to do, we can help you better then. C++ has some good tools available, including templates and overloading, both of which sound helpful in this case.

Share:
23,596
jackhab
Author by

jackhab

Updated on January 22, 2020

Comments

  • jackhab
    jackhab over 4 years
    void foo(void **Pointer);
    
    int main ()
    {
        int *IntPtr;
    
        foo(&((void*)IntPtr));
    }
    

    Why do I get an error?

    error: lvalue required as unary ‘&’ operand
    

    Thanks

  • mmx
    mmx over 15 years
    crashmstr: It's required to explicitly cast to void** in C++. If it was a void* you wouldn't need a cast, however it's not void*, it's void**.
  • Geekoder
    Geekoder over 15 years
    However, it is interesting to note that every modification made on Pointer in foo will only affect VoidPtr and not IntPtr (since I guess it was the aim of the OP).
  • crashmstr
    crashmstr over 15 years
    Ah, sorry! I have not had to work with void pointers in a while :)
  • Darron
    Darron over 15 years
    That should be "foo( reinterpret_cast< void** >( &IntPtr ) )"
  • Rob K
    Rob K over 15 years
    Yeah, this solution isn't right. You're only copying the (uninitialized) value of IntPtr to VoidPtr in the assignment. You're not making VoidPtr point to IntPtr. You want to do void* VoidPtr = (void*)(&IntPtr);
  • Martin York
    Martin York over 15 years
    That will not work as expected. You need to add the last step of copying the conetent back from VoidPtr into IntPtr
  • jackhab
    jackhab over 15 years
    I use void** because I have an array of void pointers and the function returns one of the pointers inside void** argument.
  • Johannes Schaub - litb
    Johannes Schaub - litb over 15 years
    well, casting to void** is like casting to int** in that regard. void** is nothing special. the questioner should use void*
  • Johannes Schaub - litb
    Johannes Schaub - litb about 15 years
    you have a int pointer in your question not an array of void pointers, though.
  • Tobias Wärre
    Tobias Wärre almost 13 years
    @Johannes, except that foo takes a void** and not a void* which is strictly speaking a type mismatch. And also, it helps to understand the flow, there is little gain of speaking of a pointer-to-a-pointer as a pointer when readability comes into concern.