reinterpret_cast vs. static_cast for writing bytes in standard-layout types?
Asked Answered
N

1

9

I need to write to individual bytes of some integer types. Should I used reinterpret_cast, or should I use static_cast via void*?

(a)

unsigned short v16;
char* p = static_cast<char*>(static_cast<void*>(&v16));
p[1] = ... some char value
p[0] = ... some char value

or (b)

unsigned short v16;
char* p = reinterpret_cast<char*>(&v16);
p[1] = ... some char value
p[0] = ... some char value

According to static_cast and reinterpret_cast for std::aligned_storage 's answer both should be equivalent --

-- if both T1 and T2 are standard-layout types and the alignment requirements of T2 are no stricter than those of T1

I'm leaning towards reinterpret_cast as that is essentially what I'm doing, isn't it?

Are there any other things to consider, specifically looking at Visual-C++ and VC8, the version we're currently compiling on? (x86 only atm.)

Northwest answered 8/7, 2014 at 8:22 Comment(0)
H
13

In this case (converting object pointers), reinterpret_cast is identical to the two nested static_cast via void*

5.2.10 Reinterpret cast [expr.reinterpret.cast]

7 An object pointer can be explicitly converted to an object pointer of a different type.72 When a prvalue v of object pointer type is converted to the object pointer type “pointer to cv T”, the result is static_cast<cv T*>(static_cast<cv void*>(v)). 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.

It is better to use reinterpret_cast to signal your intent here.

UPDATE: as mentioned in the comments, this was apparently added in C++11, although most C++98 compilers already supported it (see also this Q&A)

Homochromous answered 8/7, 2014 at 8:28 Comment(10)
By the way, it is a novelty in C++11. C++98 seems to have no such clause.Vizor
@AndreyChernyakhovskiy OK, that's good to know, but I think that the semantics were identical.Homochromous
As far as I could make it out, there was only one thing you might legally do in C++98 with a reinterpret_cast-produced pointer, namely, to reinterpret_cast it back.Vizor
@AndreyChernyakhovskiy I found another Q&A where they claim that most c++98 compilers already supported this, and it was made formally legal in c++11Homochromous
I think reinterpret_cast has always been the most natural and common way to do the cast, and I was always puzzled that that wasn't reflected in the standard.Vizor
I'd use reinterpret_cast... but do watch out for byte-endianness on your platform. p[0] might not be the lower 8 bits of your unsigned short.Squab
@Andre - heh :-) guess what the original code's purpose wasNorthwest
@MartinBa Look for helper functions on your platform. Such as htons/ntohs/htonl/ntohl. POSIX-compliant as I recall.Squab
@Homochromous - it's OK. I guess the reinterpret_cast mess doesn't get any clearer than this :-) accepted.Northwest
@MartinBa tnx, and reinterpret_cast is as verbose as it is for precisely that reason: otherwise it would be a hidden mess :-)Homochromous

© 2022 - 2024 — McMap. All rights reserved.