Why can I use static_cast With void* but not With char* - c++

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*.

Related

Casting an arbitrary integer to void*

Recently I encountered code that did this:
static_assert(sizeof(void*) >= sizeof(size_t));
size_t idx = get_index_to_array();
void* ptr = (void*)idx;
Essentially using a void* pointer provided by a third party library to store an index into an array to save an allocation.
Assuming that the pointer will neither be dereferenced nor freed/deleted at any point, and will be only used to cast back to the original value, is this code strictly conforming C++ (per the C++17 standard, if that matters)?
Asuming that the pointer will not get dereferenced nor freed/deleted at any point and will be only used to cast back to the original value, is this code strictly conforming C++ (per the C++17 standard, if that matters)?
It is conforming.
Since there is no compatible static cast, this explicit type conversion (colloquially called C-style cast) performs a reinterpret cast. Of this, the standard says (quoting the latest draft):
[expr.reinterpret.cast]
A value of integral type or enumeration type can be explicitly converted to a pointer.
A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value; mappings between pointers and integers are otherwise implementation-defined.
If, as you say, this void* pointer will not be used for anything but being cast back to an int, then yes, this code is fine.
The C-style cast in (void*)idx falls back to a reinterpret_cast when all other casts fail (such as static_cast). Usually reinterpret cast is a dangerous thing, but it does come with the guarantee that casting to an intermediate type, then back to the original type, will always yield the original value. Thus, your code, under the stated constraints, is fine.

Static_cast integer address to pointer

Why do you need a C-style cast for the following?
int* ptr = static_cast<int*>(0xff); // error: invalid static_cast from type 'int'
// to type 'int*'
int* ptr = (int*) 0xff; // ok.
static_cast can only cast between two related types. An integer is not related to a pointer and vice versa, so you need to use reinterpret_cast instead, which tells the compiler to reinterpret the bits of the integer as if they were a pointer (and vice versa):
int* ptr = reinterpret_cast<int*>(0xff);
Read the following for more details:
Type conversions
You need a C-style cast or directly the reinterpret_cast it stands for when casting an integer to a pointer, because the standard says so for unrelated types.
The standard mandates those casts there, because
you are doing something dangerous there.
you are doing something very seldom useful.
you are doing something highly implementation-dependent.
most times, that is simply a programming-error.
When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?
Regular cast vs. static_cast vs. dynamic_cast
Being late to the party I found that the following works only using static casts:
int* ptr1 = static_cast<int*>(static_cast<void*>(static_cast<unsigned char*>(nullptr) + 0xff));
This way you don't translate the constant directly to a pointer, instead you add it as a bytewise offset to the nullptr.

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
}

What is the difference between static_cast and reinterpret_cast? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
When should static_cast, dynamic_cast and reinterpret_cast be used?
I'm using c function in c++, where a structure passed as a void type argument in c is directly stored that same structure type.
eg in C.
void getdata(void *data){
Testitem *ti=data;//Testitem is of struct type.
}
to do the same in c++ i use static_cast:
void foo::getdata(void *data){
Testitem *ti = static_cast<Testitem*>(data);
}
and when i use reinterpret_cast it does the same job, casting the struct
when i use Testitem *it=(Testitem *)data;
this does the same thing too.
But how is the structure gets affected by using the three of them.
A static_cast is a cast from one type to another that (intuitively) is a cast that could under some circumstance succeed and be meaningful in the absence of a dangerous cast. For example, you can static_cast a void* to an int*, since the void* might actually point at an int*, or an int to a char, since such a conversion is meaningful. However, you cannot static_cast an int* to a double*, since this conversion only makes sense if the int* has somehow been mangled to point at a double*.
A reinterpret_cast is a cast that represents an unsafe conversion that might reinterpret the bits of one value as the bits of another value. For example, casting an int* to a double* is legal with a reinterpret_cast, though the result is unspecified. Similarly, casting an int to a void* is perfectly legal with reinterpret_cast, though it's unsafe.
Neither static_cast nor reinterpret_cast can remove const from something. You cannot cast a const int* to an int* using either of these casts. For this, you would use a const_cast.
A C-style cast of the form (T) is defined as trying to do a static_cast if possible, falling back on a reinterpret_cast if that doesn't work. It also will apply a const_cast if it absolutely must.
In general, you should always prefer static_cast for casting that should be safe. If you accidentally try doing a cast that isn't well-defined, then the compiler will report an error. Only use reinterpret_cast if what you're doing really is changing the interpretation of some bits in the machine, and only use a C-style cast if you're willing to risk doing a reinterpret_cast. In your case, you should use the static_cast, since the downcast from the void* is well-defined in some circumstances.

Which cast to use; static_cast or reinterpret_cast?

int i = 1000;
void *p = &i;
int *x = static_cast<int*>(p);
int *y = reinterpret_cast<int*>(p);
which cast should be used to convert from void* to int* and why?
static_cast provided that you know (by design of your program) that the thing pointed to really is an int.
static_cast is designed to reverse any implicit conversion. You converted to void* implicitly, therefore you can (and should) convert back with static_cast if you know that you really are just reversing an earlier conversion.
With that assumption, nothing is being reinterpreted - void is an incomplete type, meaning that it has no values, so at no point are you interpreting either a stored int value "as void" or a stored "void value" as int. void* is just an ugly way of saying, "I don't know the type, but I'm going to pass the pointer on to someone else who does".
reinterpret_cast if you've omitted details that mean you might actually be reading memory using a type other than the type is was written with, and be aware that your code will have limited portability.
By the way, there are not very many good reasons for using a void* pointer in this way in C++. C-style callback interfaces can often be replaced with either a template function (for anything that resembles the standard function qsort) or a virtual interface (for anything that resembles a registered listener). If your C++ code is using some C API then of course you don't have much choice.
In current C++, you can't use reinterpret_cast like in that code. For a conversion of void* to int* you can only use static_cast (or the equivalent C-style cast).
For a conversion between different function type pointers or between different object type pointers you need to use reinterpret_cast.
In C++0x, reinterpret_cast<int*>(p) will be equivalent to static_cast<int*>(p). It's probably incorporated in one of the next WPs.
It's a misconception that reinterpret_cast<T*>(p) would interpret the bits of p as if they were representing a T*. In that case it will read the value of p using p's type, and that value is then converted to a T*. An actual type-pun that directly reads the bits of p using the representation of type T* only happens when you cast to a reference type, as in reinterpret_cast<T*&>(p).
As far as I know, all current compilers allow to reinterpret_cast from void* and behave equivalent to the corresponding static_cast, even though it is not allowed in current C++03. The amount of code broken when it's rejected will be no fun, so there is no motivation for them to forbid it.
When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used? gives some good details.
From the semantics of your problem, I'd go with reinterpret, because that's what you actually do.