Is reinterpret_cast<char *> the only valid use of reinterpret_cast?
Asked Answered
T

3

12

I recently learned that the C++ standard contains "strict aliasing rules", which forbid referencing the same memory location via variables of different types.

However, the standard does allows for char types to legally alias any other type. Does this mean reinterpret_cast may legally only be used to cast to type char * or char &?

I believe strict aliasing allows for casting between types in an inheritance hierarchy, but I think those situations would tend to use dynamic_cast<>?

Thank you

Tjaden answered 12/5, 2016 at 4:51 Comment(0)
R
11

There are many different uses of reinterpret_cast. The cppreference page lists 11 different cases.

I guess you are only asking about cases 5 and 6: casting T * to U *, and casting T to U &.

In those cases, the cast is legal so long as there is not an alignment violation. The strict aliasing issue only arises if you read or write through the resulting expression.

Your summary of the strict aliasing rule in your first paragraph is a great oversimplification, in general there are several legal types for U. The same cppreference page gives a bulleted list of cases; you can read the exact text of the rule in a C++ standard draft.

Revolution answered 12/5, 2016 at 5:6 Comment(5)
What use could it even have to reinterpret but be unable to make use of the different interpretation?!Fronia
@noein that question is too broad for comments. Maybe post a new questionRevolution
@Revolution : can you please give an example of why read is also violation/UB . If we have a read-only buffer that we are using reinterpret_cast depending on the binary format we store (int , float , bit) , is it still not allowed given that the storage buffer is read only ?Tiannatiara
@Tiannatiara the cppreference link in my answer explains the strict aliasing rule, under section "type aliasing". This refers to reading and writing .Revolution
@Revolution : thanks , yes i understand it talks about reading as well but i did not understand the rationale , can you please provide any code snippet or example where it would go wrong/undefined ?Tiannatiara
D
8

There are other uses of reinterpret_cast that are useful.

Pointer to integer type

Yes, sometime over would like to store the value of a pointer in a integer type.

The only way to do this with C++ style casts is with reinterpret_cast.

Example:

auto pointerValue = reinterpret_cast<std::uintptr_t>(pointer);

Storing objects in raw memory block

Sometime you want to store data on the stack but initializing it later. Using dynamic allocations and pointers won't using the stack. std::aligned_storage does a great job as raw, aligned memory block.

struct MyStruct {
    int n;
    std::string s;
};

// allocated on automatic storage
std::aligned_storage<sizeof(MyStruct), alignof(MyStruct)>::type storage;

// actually initialize the object
new (&storage) MyStruct;

// using the object
reinterpret_cast<MyStruct*>(&storage)->n = 42;

I'm sure there is a lot of other uses that I don't know, but these are the one I already used.

Daegal answered 12/5, 2016 at 5:9 Comment(3)
note: it's also legal to form the pointer first, e.g. auto *p = reinterpret_cast<MyStruct *>(&storage); new(&storage) MyStruct; p->n = 42;Revolution
@Revolution Or, you know, auto* p = new(&storage) MyStruct; and avoid the cast altogether.Dehumidify
@Dehumidify well the point of this was to illustrate legal uses of reinterpret_castRevolution
P
6

You can also use a reinterpret_cast to cast a pointer type to an integer type:

char* ptr = /* ... */
uintptr_t ptrInt = reinterpret_cast<uintptr_t>(ptr);

The specific integer value you get back isn't portable across platforms, but this is a safe and well-defined operation.

Parament answered 12/5, 2016 at 4:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.