Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When does reinterpret_cast modify bits?

From the C++ standard:

5.2.10.3

The mapping performed by reinterpret_cast might, or might not, produce a representation different from the original value.

I've been trained at this very site to believe and repeat this. (Even if it's possibly just trivia). A reinterpret_cast from float* to int* is allowed to produce a different bit pattern. The only guarantee is that reinterpret_cast-ing that result back to float* will produce the original bit pattern.

My question: Does this ever happen? Is there an existing, real-world platform or CPU or compiler that actually reinterpret_casts to a different bit pattern? If not, are there any real-world situations where reinterpret_cast has any runtime overhead?

In all my experience with reinterpret_cast, the cast was a directive to the compiler, not the runtime.

like image 529
Drew Dormann Avatar asked Jul 09 '14 05:07

Drew Dormann


2 Answers

Pointers can in principle be different sizes. The largest pointer, if there is any difference (disregarding member pointers, talking about real pointers), is char*, since a char by definition is a byte and can be anywhere, no alignment. void* must be able to represent char*.

On a system with int* using fewer bits than char*, reinterpret-casting in that direction might be a bit risky.

I think with these pointers (heh) you can find this in the standard. It's the requirement about void* being large enough for any pointer, and the thing about alignment: the stricter/larger, the fewer bits needed for pointer to that type. But I have not ever heard of any extant system where there is such difference.


Standardese regarding void* being able to represent char*:

C++11 §3.9.2/4:


A pointer to cv-qualified (3.9.3) or cv-unqualified void can be used to point to objects of unknown type. Such a pointer shall be able to hold any object pointer. An object of type cv void* shall have the same representation and alignment requirements as cv char*

The “any object pointer” implies vaguely that there are different sizes of pointer.


Standaredese regarding the alignment of referent:

C++11 §5.2.10/7:


An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue v of type “pointer to T1” is converted to the type “pointer to cv T2”, the result is static_cast<cv T2*>(static_cast<cv void*>(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment requirements of T2 are no stricter than those of T1, or if either type is void. Converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value. The result of any other such pointer conversion is unspecified.

It’s worth noting that later on in the standard there is some support for C-style emulation of class derivation, that apparently contradicts the “any other” at the end above:

C++11 §9.2/20,


A pointer to a standard-layout struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa.

In this case the two objects necessarily have the same alignment, while the previous cited paragraph talked only about alignment of types – but clearly the formal little contradiction is not a practical problem, as I see it.

like image 196
Cheers and hth. - Alf Avatar answered Oct 16 '22 14:10

Cheers and hth. - Alf


I've worked on platforms where char* was larger than int*, and on platforms where they had a different layout, even though the size was the same. Neither of the machines in question are particularly relevant today, however (although the second, the PDP-10, was one of the more important machines in its heyday). It's also conceivable that some compilation modes on an Intel in native mode (or what used to be called native mode) would "normalize" pointers in a reinterpret_cast, or even an implicit conversion, in order to facilitate address comparisons. It's also conceivable (although I've not seen it) that such conversions enforce correct alignment, e.g. a conversion from char* to int* might force the 2 low-order bits to 0. In practice, however, I don't think, today, that you're likely to see a reinterpret_cast make any changes between data pointer types. The issue is more historic. (But I'm not sure about modern embedded processors. From what I understand, many of them are word addressing, and so if sizeof(int) != sizeof(char), they're likely to need a special format to address char.)

like image 44
James Kanze Avatar answered Oct 16 '22 14:10

James Kanze