Why would you convert to a void pointer? - c++

I saw the following code in this question:
class CFoo
{
int a;
public:
CFoo():a(1){}
~CFoo(){}
getNum(){return a;}
};
void tfunc(void* data)
{
CFoo* foo = static_cast<CFoo*>(data);
std::cout << "Number: " << foo->getNum();
delete foo;
}
int main()
{
CFoo* foo = new CFoo;
void* dt = static_cast<void*>(foo);
tfunc(dt); // or tfunc(static_cast<void*>(food));
return 0;
}
and started to wonder about why you would convert a pointer to a type to a pointer to void instead of simply assign the void pointer the the actual pointer. Like when calling tfunc in the code code above, he could have called it like tfunc(&foo) instead of converting the pointer to a type to void pointer as he did using the static cast static_cast<void*>(foo);, right?

The wording of your question is a bit confusing, you are not actually asking why converting to void*, you are asking why use explicit casting instead of rely on implicit casting, i.e.
tfunc(static_cast<void*>(food)); // explicit casting
vs
tfunc(food); // implicit casting
The issue is a bit more general than casting to void*. Unfortunately C++ allows a fair amount of implicit dangerous castings. E.g. between singed and unsigned, from a wider integer or floating point to a narrower one, conversions to bool and conversions to void*. All this conversions have the potential to silently introduce bugs in the code. c++11 did a little step in the right direction by not allowing narrowing in the new uniform initializer syntax {}, but due to backward compatibility all previous implicit casts are still allowed.
That's why explicit casting is encouraged. It helps showing the intent of the writer. It shows that the conversion is explicitly desired, as opposed to happening silently, possibly without the author knowledge. Also very important, it helps on code review or when reading the code by being a flag sort of "Here there is cast. Be aware of that when you look over this code"

From the example above I do not understand why the signature of function tfunc is void tfunc(void* data) and not void tfunc(class CFoo* data).
Anyway, it is valid to convert a pointer to any type T into a void *, and it is valid to convert such a pointer back to T* later. The conversion from T* can be implicit, whereas conversion from void* back to T* needs to be explicit. So, in your example, tfunc(foo) is equivalent to tfunc(static_cast<void*>(foo)) and to tfunc(dt).
Concerning the point "conversion of CFoo* to void*, there is a standard conversion (cf. this c++ online draft standard):
4 (1) Standard conversions are implicit conversions with built-in
meaning. Clause 4 enumerates the full set of such conversions.
4.10 Pointer conversions (2) A prvalue of type “pointer to cv T,” where T is an object type, can be converted to a prvalue of type
“pointer to cv void”. The result of converting a non-null pointer
value of a pointer to object type to a “pointer to cv void” represents
the address of the same byte in memory as the original pointer value.
...
I'd prefer the implicit conversion over explicit conversions, as the the built-in meaning of the (implicit) standard conversion meets exactly the requirements.
A use case for void* in a function signature could be that one wants to pass objects of unrelated type and decide inside the function to which type it has to be casted back. Suppose, for example, a function handling callbacks for different response types, and each response type might pass different (class hierarchically independent) objects:
void someCallback(int responseType, void *context) {
if(responseType == 1) {
CFoo1* foo1 = static_cast<CFoo1*>(context);
...
}
else {
CFoo2* foo2 = static_cast<CFoo2*>(context);
...
}
}

Related

Do function pointer addresses hold after conversions?

From what I understand, casting function pointers to different types is allowed by the C++ standard (as long as one never invokes them):
int my_func(int v) { return v; }
int main() {
using from_type = int(int);
using to_type = void(void);
from_type *from = &my_func;
to_type *to = reinterpret_cast<to_type *>(from);
// ...
}
Moreover, there is no undefined behavior if I cast the pointer back to its original type and invoke it.
So far, so good. What about the following, then?
const bool eq = (to == reinterpret_cast<to_type *>(my_func));
Does the address hold, too, after the conversion, or is this not guaranteed by the standard?
While this is irrelevant to the question, a possible scenario is when one goes hard on type erasure. If the address holds, something can be done without having to know the original function type.
From [expr.reinterpret.cast].6 (emphasis mine):
A function pointer can be explicitly converted to a function pointer of a different type.
[...]
Except that converting a prvalue of type “pointer to T1” to the type
“pointer to T2” (where T1 and T2 are function types) and back to its
original type yields the original pointer value, the result of such a
pointer conversion is unspecified.
So, the standard explicitly allows casting function pointers to different FP types and then back. This is an exception to the general rule that reinterpret_casting function pointers is unspecified.
In my understanding, that means to == reinterpret_cast<to_type *>(my_func) need not necessarily be true.

Why can I use static_cast With void* but not With char*

I know that reinterpret_cast is primarily used going to or from a char*.
But I was surprised to find that static_cast could do the same with a void*. For example:
auto foo "hello world"s;
auto temp = static_cast<void*>(&foo);
auto bar = static_cast<string*>(temp);
What do we gain from using reinterpret_cast and char* over static_cast and void*? Is it something to do with the strict aliasing problem?
Generally speaking, static_cast will do cast any two types if one of them can be cast to the other implicitly. That includes arithmetic casts, down-casts, up-casts and cast to and from void*.
That is, if this cast is valid:
void foo(A a);
B b;
foo(b);
Then the both static_cast<B>(a) and static_cast<A>(b) will also be valid.
Since any pointer can be cast implicitly to void*, thus your peculiar behavior.
reinterpret_cast do cast by reinterpreting the bit-pattern of the values. That, as you said in the question, is usually done to convert between unrelated pointer types.
Yes, you can convert between unrelated pointer types through void*, by using two static_cast:
B *b;
A *a1 = static_cast<A*>(b); //compiler error
A *a2 = static_cast<A*>(static_cast<void*>(b)); //it works (evil laugh)!
But that is bending the rules. Just use reinterpret_cast if you really need this.
Your question really has 2 parts:
Should I use static_cast or reinterpret_cast to work with a pointer to the underlying bit pattern of an object without concern for the object type?
If I should use reinterpret_cast is a void* or a char* preferable to address this underlying bit pattern?
static_cast: Converts between types using a combination of implicit and user-defined conversions
In 5.2.9[expr.static.cast]13 the standard, in fact, gives the example:
T* p1 = new T;
const T* p2 = static_cast<const T*>(static_cast<void*>(p1));
It leverages the implicit cast:
A prvalue pointer to any (optionally cv-qualified) object type T can be converted to a prvalue pointer to (identically cv-qualified) void. The resulting pointer represents the same location in memory as the original pointer value. If the original pointer is a null pointer value, the result is a null pointer value of the destination type.*
There is however no implicit cast from a pointer of type T to a char*. So the only way to accomplish that cast is with a reinterpret_cast.
reinterpret_cast: Converts between types by reinterpreting the underlying bit pattern
So in answer to part 1 of your question when you cast to a void* or a char* you are looking to work with the underlying bit pattern, reinterpret_cast should be used because it's use denotes to the reader a conversion to/from the underlying bit pattern.
Next let's compare void* to char*. The decision between these two may be a bit more application dependent. If you are going to use a standard library function with your underlying bit pattern just use the type that function accepts:
void* is used in the mem functions provided in the cstring library
read and write use char* as inputs
It's notable that C++ specific libraries prefer char* for pointing to memory.
Holding onto memory as a void* seems to have been preserved for compatibility reasons as pointer out here. So if a cstring library function won't be used on your underlying bit patern, use the C++ specific libraries behavior to answer part 2 of your question: Prefer char* to void*.

Casting Class Pointer to Void Pointer [duplicate]

I have seen and used this many times is C++, specially in various thread implementations. What I wonder is if there are any pitfalls/ issues of doing this? Is there any way that we could run in to an error or undefined condition when we are casting to void* and back again? How should we resolve such issues if there are any?
Thank you.
This is perfectly valid. Here is what standard has to say about it:
§4.10 Pointer conversions
2 An rvalue of type "pointer to cv T," where T is an object
type, can be converted to an rvalue of type "pointer to cv
void." The result of converting a "pointer to cv T" to a "pointer
to cv void" points to the start of the storage location where the
object of type T resides, as if the object is a most derived
object (1.8) of type T (that is, not a base class subobject).
which means you can convert your pointer to class to a void pointer. And ...
§5.2.9 Static cast
10 An rvalue of type "pointer to cv void" can be explicitly
converted to a pointer to object type. A value of type pointer
to object converted to "pointer to cv void" and back to the
original pointer type will have its original value.
which means you can use static_cast to convert a void pointer back to an original class pointer.
Hope it helps. Good Luck!
I have not seen casting to void* much in C++. It is a practice in C that is actively avoided in C++.
Casting to void* removes all type safety.
If you use reinterpret_cast or static_cast to cast from a pointer type to void* and back to the same pointer type, you are actually guaranteed by the standard that the result will be well-defined.
The hazard is that you may cast a void* to the wrong type, since you are no longer assured of what the correct type was.
In C++ you don't need the static cast to get to void*:
int main()
{
CFoo* foo = new CFoo;
void* dt = foo;
tfunc(dt); // or tfunc(foo);
return 0;
}
NB: your implementation of tfunc() is quite correct in that it does need the cast.
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.
The only thing the standard grants is that, given A* pa, (A*)(void*)pA == pA.
A a consequence
void* pv = pA;
A* pA2 = (A*)pv;
pA2->anything ...
will be te same as pA->anything ...
Everything else is "not defined", ad -in fact- is somehow implementation dependent.
Based on my experience, here are some known pitfalls:
Consider A derived form B, pA and pB to be A* and B*. pB=pA makes pB to point to the base of A. That doesnt mean that pB and pA are the same address. hence pB = (B*)(void*)pA can actually point anywhere else into A (although single inheritance objects are commonly implemented sharing the same origin, so it apparently works fine)
The same is viceversa: Assuming pB actually is pointing to an A, pA = (A*)(void*)pB don't necessarily point correctly to the A object. The correct way is pA = static_cast<A*>(pB);
If the above points can work with the most of single inheritance implementations, will never work with multiple imheritance for bases other than the first: consider class A: public Z, public B { ... }; if Z is not empty, given an A, the B subcomponent will not have the same A address. (and multiple inheritance in C++ is everywhere an iostream is)
Sometimes things depend also on the platform: (char*)(void*)pI (where pI points to an integer) will not be the same as "*pI if *pI in(-128..+127)" (it will be only on little endian machines)
In general don't assume conversion between types works just changing the way an address is interpreted.
I know a lot of functions within driver etc. using void pointers to return data to the caller, the schema is mostly the same:
int requestSomeData(int kindOfData, void * buffer, int bufferSize);
This function can take different data types as parameter.
What they do is using bufferSize as a parameter to avoid writing to memory places they should not write to.
If the bufferSize does not match or is smaller than the data that shall be returned, the function will return an error code instead.
Anyway: Avoid using them or think threefold before writing any code.
Is this valid?
Yes, it is valid as per standard § 5.2.9.7
A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T,” where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. The null pointer value is converted to the null pointer value of the destination type. A value of type pointer to object converted to “pointer to cv void” and back, possibly with different cv-qualification, shall have its original value. [ Example:
T* p1 = new T;
const T* p2 = static_cast<const T*>(static_cast<void*>(p1));
bool b = p1 == p2; // b will have the value true.

Is reinterpret_cast and c-style cast compatible (by C++ standard)?

The C++ standards mentions that reinterpret_cast is implementation defined, and doesn't give any guarantees except that casting back (using reinterpret_cast) to original type will result in original value passed to first.
C-style casting of at least some types behaves much the same way - casting back and forth results with the same value - Currently I am working with enumerations and ints, but there are some other examples as well.
While C++ standard gives those definitions for both cast-styles, does it also give the same guarantee for mixed casts? If library X returns from function int Y() some enum value, can use any of above casts, without worrying what cast was used to convert initial enum to int in Y's body? I don't have X's source code, so I cannot check (and it can change with next version anyway), and things like that are hardly mentioned in documentation.
I know that under most implementations in such cases both casts behave the same; my question is: what does C++ standard say about such cases - if anything at all.
C++ defines the semantic of the C cast syntax in terms of static_cast, const_cast and reinterpret_cast. So you get the same guaranteed for the same operation whatever syntax you use to achieve it.
reinterpret_cast can only be used for specific conversions:
Pointer to (sufficiently large) integer, and the reverse
Function pointer to function pointer
Object pointer to object pointer
Pointer-to-member to pointer-to-member
lvalue expression to reference
plus (conditionally) function pointer to object pointer and the reverse. In most cases, the converted value is unspecified, but there is a guarantee that a conversion followed by its reverse will yield the original value.
In particular, you can't use reinterpret_cast to convert between integer an enumeration types; the conversion must be done using static_cast (or implicitly, when converting an unscoped enumeration to an integer type), which is well defined for sufficiently large integer types. The only possible problem is if the library did something completely insane such as return reinterpret_cast<int&>(some_enum);
A C-style cast will perform either a static_cast or a reinterpret_cast, followed by a const_cast, as necessary; so any conversion that's well-defined by static_cast is also well-defined by a C-style cast.
No, reinterpret_cast is not equivalent to a C style cast. C style casts allow casting away const-volatile (so it includes the functionality of const_cast) not allowed in reinterpret_cast. If static_cast is allowed between the source and destination types, it will perform a static_cast which has different semantics than reinterpret_cast. It the conversion is not allowed, it will fallback to reinterpret_cast. Finally there is a corner case where the C cast cannot be represented in terms of any of the other casts: it ignores access specifiers.
Some examples that illustrate differences:
class b0 { int a; };
class b1 { int b; };
class b2 { int c; };
class d : public b0, public b1, b2 {};
int main() {
d x;
assert( static_cast<b1*>(&x) == (b1*)&x );
assert( reinterpret_cast<b1*>(&x) != (b1*)&x ); // Different value
assert( reinterpret_cast<b2*>(&x) != (b2*)&x ); // Different value,
// cannot be done with static_cast
const d *p = &x;
// reinterpret_cast<b0*>(p); // Error cannot cast const away
(b0*)p; // C style can
}

conversion for void* as a method argument

For a method with an argument of void* is C++ employing static/reinterpret_cast to make the conversion or is there a different mechanism in play here?
void foo(void* p)
{
// ... use p by casting it back to Base first, using static/reinterpret cast
}
Base* base(new Derived);
foo(base); // at this exact line, is there a static/reinterpret_cast going on under the covers?
I am asking because it seems that on one hand the standard says that for c-style cast, C++ will go and try a C++ cast (static, reinterpret, const) until something that works is found. However I can't find a reasonable explanation as to what goes on when a method with a void* argument is called. On the face of thing there is no cast, so what happens?
The language specification does not express the behavior in terms of static_cast or reinterpret_cast in this case. It just says that the pointer base is implicitly converted to void * type. Conversions that can be performed implicitly are called standard conversions in C++. Conversion of any object pointer type to void * is one of the standard conversions from pointer conversions category.
It is true that this is the same conversion that can be preformed explicitly by static_cast, but static_cast is completely irrelevant in this case. Standard conversions in C++ work "by themselves" without involving any specific cast operators under the cover.
In fact, it is the behavior of static_cast that is defined in terms of standard conversions for such cases, not the other way around.