std::memcpyCopies count bytes from the object pointed to by src to the object pointed to by dest . Both objects are reinterpreted as arrays of unsigned char. If the objects overlap, the behavior is undefined. If either dest or src is an invalid or null pointer, the behavior is undefined, even if count is zero.
If you are going to copy bytes (which I usually don't) std::memcpy is fine by my standard. My advice is never to use std::memcpy for any purpose. If you want to copy bytes, use std::copy . If you want to copy bytes in an implementation-specific way, use std::copy and the appropriate cast to warn others.
std::function cannot be TriviallyCopyable (or conditionally TriviallyCopyable ) because as a generic callable object wrapper it cannot assume that the stored callable is TriviallyCopyable .
memcpy is usually naive - certainly not the slowest way to copy memory around, but usually quite easy to beat with some loop unrolling, and you can go even further with assembler.
The standard may fail to say properly that this is allowed, but it's almost certainly supposed to be, and to the best of my knowledge, all implementations will treat this as defined behaviour.
In order to facilitate the copying into an actual char[N]
object, the bytes making up the f
object can be accessed as if they were a char[N]
. This part, I believe, is not in dispute.
Bytes from a char[N]
that represent a uint32_t
value may be copied into an uint32_t
object. This part, I believe, is also not in dispute.
Equally undisputed, I believe, is that e.g. fwrite
may have written the bytes in one run of the program, and fread
may have read them back in another run, or even another program entirely.
Because of that last part, I believe it does not matter where the bytes came from, as long as they form a valid representation of some uint32_t
object. You could have cycled through all float
values, using memcmp
on each until you got the representation you wanted, that you knew would be identical to that of the uint32_t
value you're interpreting it as. You could even have done that in another program, a program that the compiler has never seen. That would have been valid.
If from the implementation's perspective, your code is indistinguishable from unambiguously valid code, your code must be seen as valid.
Is my first example (and the linked answer) well defined?
The behaviour isn't undefined (unless the target type has trap representations† that aren't shared by the source type), but the resulting value of the integer is implementation defined. Standard makes no guarantees about how floating point numbers are represented, so there is no way to extract mantissa etc from the integer in portable way - that said, limiting yourself to IEEE 754 using systems doesn't limit you much these days.
Problems for portability:
You can use std::numeric_limits::is_iec559
to verify whether your assumption about representation is correct.
† Although, it appears that uint32_t
can't have traps (see comments) so you needn't be concerned. By using uint32_t
, you've already ruled out portability to esoteric systems - standard conforming systems are not require to define that alias.
Your example is well-defined and does not break strict aliasing. std::memcpy
clearly states:
Copies
count
bytes from the object pointed to by src to the object pointed to by dest. Both objects are reinterpreted as arrays ofunsigned char
.
The standard allows aliasing any type through a (signed/unsigned) char*
or std::byte
and thus your example doesn't exhibit UB. If the resulting integer is of any value is another question though.
use i to extract f's sign, exponent & significand
This however, is not guaranteed by the standard as the value of a float
is implementation-defined (in the case of IEEE 754 it will work though).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With