Casting to void* and Back to Original_Data_Type*
What I wonder is if there are any pitfalls/ issues of doing this?
You need to be absolutely sure while casting the the void*
back to the particular type, if you don't, you end up with an Undefined behavior and a potential disaster. Once you use void *
you lose type safety.It is difficult to keep track of what type a void *
is actually pointing to, there is no way to guarantee or determine that it indeed points to the type to which you are going to typecast it back to.
Is there any way that we could run in to an error or undefined condition when we are casting to void* and back again?
Yes, the scenario mentioned in #1
.
How should we resolve such issues if there are any?
Avoid using void *
in C++ completely, instead use templates and inheritance.
In C you might absoultely need it in certain situations but try to keep its use to a minimum.
Bottomline,
C/C++ allows you to shoot yourself in foot, it is up to you to do or not do so.
Casting to void* and typedefs in C++
It shouldn't cause any trouble, but it will only give API users a false sense of security (as any arbitrary pointer will also work). There's nothing to prevent the compiler from complaining if you do something like:
int i;
// ....
modifyIndex(&i);
So while you won't have any problems, you won't have any compile-time checks and enforcements either.
Do note that you have the choice of simply declaring the class without actually defining it.
The proper way to solve the void-pointer "problem" (and it's not really a problem, it's just an aspect of C (and thus C++) which may make code difficult to maintain without proper care/documentation) is to somehow expose Index
as an opaque type; e.g.
// index.h
class Index;
// ...
void modifyIndex(Index *i);
Convert void* to a dynamic type
instead of
char* myType= typeid(i).name();//get the name of type of "i"
int p = *((myType*) pointer); // how to implement?
use
typedef decltype(i) myType;
myType p = *((myType*) pointer);
or better:
typedef decltype(i) myType;
auto p = *reinterpret_cast<myType*>(pointer);
Works with c++11 or later. If you want to decltype
on older c++ compilers, it is emulated in boost.
Edit. This is probably different from what you wanted to do, which I suppose is something like this:
void myFunction(void* unknownParam) {
typedef (realTypeOf unknownParam) RealType; // <-- this is not real c++
RealType &a = *reinterpret_cast<RealType*>(unknownParam)
//do stuff using 'a'
}
This is not possible in C++, but there is a reason: it doesn't make much sense.
And the reason is that for myFunction
to be valid the //do stuff using 'a'
part should be valid for whatever type RealType
ends up being. As such, it cannot rely on any feature the RealType
type have: it cannot use any of its methods, it cannot use any operator, it cannot even know whether it is a class or not. Basically, you cannot do anything more with it than what you would already be able to do on a void*
, so giving the type a name doesn't really help you much.
A language feature that is similar to what you want (but not quite it) is type reflection, which is not present in C++, but you can find it in language such as Java, Objective-C or C#. Basically, you ask the object itself if it has a certain method, and eventually call it. An example in Objective-C
-(void)myFunction:(id)unknownParam {
if([unknownParam respondsToSelector:@selector(myMethod)])
[unknownParam performSelector:@selector(myMethod)]
}
Is there a safe way to cast void* to class pointer in C++
Yes, static_cast
is correct here.
Assuming that the void*
value is only copied inside the C library, static_cast
will return the original pointer value pointing to the passed object if you cast it to a pointer of the same type as it was originally.
Under some conditions you may also cast to a different type, the rules are those of reinterpret_cast
(which simply casts via two static_cast
s with void*
intermediate).
If you cast it to any type not allowed under those rules, e.g. an unrelated class type, trying to access the object through the pointer will cause undefined behavior. There is no way of detecting this mistake. You need to take care of doing it correctly yourself.
C++ Why wrong override method get called
You should just do this: void callBaseB(BaseB *p) {p->methodB(0);}
.
If you want to keep void *p
as a parameter, you need to cast it to exactly Child *
first. Either:
BaseB *b = (Child *)p;
b->methodB(0);
Or:
Child *b = (Child *)p;
b->methodB(0);
Alternatively, cast to BaseB *
before converting to void *
. Then casting from void *
back to Base *
will work.
What happens here is that the BaseB
subobject is at non-zero offset inside of Child
.
When you convert Child *
to BaseB *
(either explicitly with a cast, or implicitly, either by assigning pointers or by calling a method of BaseB
on the pointer), the compiler automatically offsets the pointer by the required amount, to point to the BaseB
subobject.
The offset is determined entirely at compile-time (unless virtual inheritance is involved), based on the two types.
When you obscure the source type using void *
, the compiler has no way to determine the correct offset, and doesn't even try to apply any offset, so you get weird behavior, because the resulting BaseB *
doesn't point to a BaseB
instance, but rather to some junk inside of Child
.
Even with virtual inheritance, despite the offset being determined at runtime, the calculation depends on the source pointer type being known.
Type punning with void * without breaking the strict aliasing rule in C99
void *
has nothing to do with type-punning. Its main purposes are:
To allow for generic allocation and freeing operations that don't care about the type of the object the caller is storing there (e.g.
malloc
andfree
).To allow a caller to pass a pointer to an arbitrary type through a function that will pass it back via a callback, (e.g.
qsort
andpthread_create
). In this case, the compiler cannot enforce type checking; it's your responsibility when writing the caller and callback to ensure that the callback accesses the object with the correct type.
Pointers to void
are also used in a few places (like memcpy
) that actually operate on an object as the overlaid unsigned char []
representation for the object. This could be seen as type-punning, but it's not an aliasing violation because char
types are allowed to alias anything to access its representation. In this case, unsigned char *
would also work, but void *
has the advantage that pointers automatically convert to void *
.
In your example, since the original type is int
and not a union, there is no legal way to type-pun and access it as short
. You could instead copy the value of x
to a union, perform well-defined type-punning there, then copy it back. A good compiler should omit the copy entirely. Alternatively, you could break the write down into char
writes and then it would be legal aliasing.
Related Topics
Gdb - List Source of Current Function Without Typing Its Name
Is There Any Function Equivalent to Matlab's Imadjust in Opencv with C++
How to Use Ms Code Coverage Tool in Command Line
Macro and Member Function Conflict
How to Share Memory Between Linux Program and Windows Program Running Through Wine (Same Computer)
Boost Serialization, Deserialization of Raw C Arrays
How to Call C or C++ Functions from Rust Code
How to Construct or Return the Underlying Deque from a Stack
How to Safely (And Easily) Count *All* Instances of a Class Within My Program
Read Qprocess Output to String
What Expressions Create Xvalues
Array Overflow (Why Does This Work)
Compiling Simple Static Opengl 4.0 Program Using Mingw, Freeglut and Glew
Cancel Async_Read Due to Timeout