-4
#include <iostream>
using namespace std;

class A
{
    public:
        A(int x){ a = x;}
        ~A();
    private:
        int a;
};

int main()
{
    A* a = new A(10);
    void** p;
    p = &a;
    return 0;
}

After compiling with g++ (GCC) 4.1.2 20080704 , I am getting following error :

test.cpp: In function 'int main()':
test.cpp:17: error: invalid conversion from 'A**' to 'void**'

Garf365
  • 3,619
  • 5
  • 29
  • 41
Undefined Behaviour
  • 729
  • 2
  • 8
  • 27
  • 6
    Yes, getting the error is quite natural because the conversion is invalid without explicit casting. Then, what is your question? – MikeCAT Aug 16 '16 at 13:29
  • p = static_cast(&a); I casted it like above. And again i am getting following error : error: invalid static_cast from type ?A**? to type ?void**? – Undefined Behaviour Aug 16 '16 at 13:31
  • This is a dangerous conversion. Consider what happens if you then do `*p = new int;`. – molbdnilo Aug 16 '16 at 13:31
  • Is there a reason you need to use a `void**`? – NathanOliver Aug 16 '16 at 13:32
  • Yes, i am trying to write some C API. and internally C++ implemnetation. Don't want to expose my internal type to user – Undefined Behaviour Aug 16 '16 at 13:33
  • Isn't that what *abstract data types* are for? – IInspectable Aug 16 '16 at 13:34
  • 4
    @vidhugangwar This conversion is so unsafe it needs `reinterpret_cast`, and you *really* need to know what you're doing. (Being confused by this usually indicates that you don't.) – molbdnilo Aug 16 '16 at 13:34
  • @MikeCAT why explicit casting is not needed for below case A* a = new A(10); void* p; p = a; – Undefined Behaviour Aug 16 '16 at 13:35
  • [passing pointers from C to C++ and vice versa](http://stackoverflow.com/questions/2076209/passing-pointers-from-c-to-c-and-vice-versa) – 001 Aug 16 '16 at 13:37
  • 2
    @vidhugangwar A `void*` points to `void`, which means it can point to anything. But a `void**` can only point to one thing - to a `void*`. – Angew is no longer proud of SO Aug 16 '16 at 13:39
  • FWIW, conversions from `A**` to `void**` are necessary to use some APIs. For example, see [CoCreateInstance](https://learn.microsoft.com/en-us/windows/desktop/api/combaseapi/nf-combaseapi-cocreateinstance). – jakar Jan 22 '19 at 19:36

3 Answers3

1

There's one star to much. void* can already hold any pointer, without casts:

int main()
{
    A* a = new A(10);
    void* p;
    p = &a;
    return 0;
}

This works for multiple levels, even:

int main()
{
    A* a = new A(10);
    A** aa = &a;
    A*** aaa = &aa;
    void* p = &aaa;
}

This works because A*** is a pointer to a A**.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • While you're right, I have to ask, does it matter, wouldn't it be kinda helpful to maintain the level of indirection as part of the pointer type? Also wouldn't your code throw the same error, as it attempts to cast from a `A***` to a `void*`. – Jonathan Mee Aug 16 '16 at 17:51
  • 1
    @JonathanMee: No, that's pretty much the point. `void*` can hold any type of pointer. `void**` holds a pointer to a `void*`. For that reason, you need **exactly** one * on `void*` here. Not 2 or 3, not 0, but 1. – MSalters Aug 16 '16 at 20:47
0

You can't just assign the value of one type (A**) to the variable of another one (void**), if it can't be converted implicitly. You need to explicitly convert value from one type to another:

class A
{
    public:
        A(int x){ a = x;}
        ~A();
    private:
        int a;
};

int main()
{
    A* a = new A(10);
    void** p;

    // use `reinterpret_cast'
    p = reinterpret_cast<void**>(&a);

    // C-style cast works but it is a bad practice in C++
    p = (void**)&a;

    return 0;
}
KolesnichenkoDS
  • 530
  • 1
  • 6
  • 20
  • 1
    I'm glad you added the `reinterpret_cast` but you should really remove the C-Style cast all together. It just encourages bad coding practices. – Jonathan Mee Aug 16 '16 at 13:51
  • Actually, this answer isn't really correct. You **can** assign a variable of some type *U* to a variable of some type *V* without a cast, as long as *U* can be implicitly converted to *V*. If *V* is `void*` then *U* can be **any** pointer. – IInspectable Aug 16 '16 at 16:31
0

You need to use reinterpret_cast:

It is purely a compiler directive which instructs the compiler to treat the sequence of bits (object representation) of expression as if it had the type new_type.

In this case your expression will be &a which has the type A** and your new_type will have the type void**:

p = reinterpret_cast<void**>(&a);

Do have a care here as C++ isn't really that fond of the void type and your code is very likely going to violate Type Aliasing Rules.

In my mind a cast to void** is an indication that a template should probably be used. Without seeing your code I can't guarantee that, but, if you want to fill me in anymore in the comments perhaps I can help.

Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288