5 ms·
Don't use reinterpret_cast for type-punning in c++, you'll end up with UB. You should instead use memcpy.
by bigcheesegs 8y ago
Don't use reinterpret_cast for type-punning in c++, you'll end up with UB. You should instead use memcpy.
- ramshorns 8y agoWhat is reinterpret_cast for, if not type punning?
- tom_ 8y agoUnadjusted conversion between pointer types that have matching cv qualifiers.
- kazinator 8y agoPointers are converted in order that they be used. Though the uses may be undefined, there is value in the conversion having a well-defined syntax. In effect, C and C++ allow certain intents to be expressed in a common way, without requiring implementations to make those intents work. This is better than having compiler-specific syntax for that sort of thing.
- kazinator 8y agoNonsense. Aliasing unlike-typed objects via memcpy is equivalent to pointer aliasing. memcpy has void pointer arguments. You're relying on the addresses of the source and destination objects being converted to void pointer. All type punning is in the hands of the implementation. The language definition provides the syntax for it, which has the virtuel that all code which attempts to do type punning expresses it in the same manner. However, the language leaves it up to implementations to define whether type punning works, and with what caveats and restrictions.
- tedunangst 8y agoExcept using memcpy specifically does not violate aliasing rules, while aliases do.
- kazinator 8y agoIt absolutely does. E.g. you can't memcpy a uint64 to a double and expect well-defined behavior. There is some hand-waving in the definition of memcpy so that copying compatible objects is well-defined.
- comex 8y ago> E.g. you can't memcpy a uint64 to a double and expect well-defined behavior. Yes, you can. The behavior is implementation-defined but not undefined. (Well, it can trigger undefined behavior if the value corresponds to a signaling NaN, or if the implementation uses a nonstandard, non-IEEE format for doubles that has other "trap representations". But it's not otherwise undefined.) The basis for this is that the aliasing rule has an explicit exception for reading or writing to objects using char pointers, i.e. byte-by-byte, regardless of the object's type. This exception is in both the C standard: https://port70.net/~nsz/c/c11/n1570.html#6.5p7 https://port70.net/~nsz/c/c11/n1570.html#6.5p7 and the C++ standard: http://eel.is/c++draft/expr.prop#basic.lval-11.8 http://eel.is/c++draft/expr.prop#basic.lval-11.8 The memcpy function is defined as copying characters, so the exception applies to it too. Both standards also explicitly define that objects (at least of POD types) have byte representations and those representations are implementation-defined (as opposed to triggering undefined behavior if you depend on them). For C: > Except for bit-fields, objects are composed of contiguous sequences of one or more bytes, the number, order, and encoding of which are either explicitly specified or implementation-defined. https://port70.net/~nsz/c/c11/n1570.html#6.2.6.1 https://port70.net/~nsz/c/c11/n1570.html#6.2.6.1 C++: http://eel.is/c++draft/basic.types http://eel.is/c++draft/basic.types
- kazinator 8y ago"access" refers to reading there. Not reading or writing. Objects may be treated as arrays of character type to the extent that their value may be examined that way. If you memcpy a uint64_t to a double, the implementation is not required to notice that the double variable's value has changed; a subsequent access to that variable can continue to refer to a register. It's not a matter of what bit pattern was stored there.