safely punning char* double c
in an open source program i
wrote, i'm reading binary information (written another program) record outputting ints, doubles,
and assorted information types. hurdles needs to
run 32-bit 64-bit machines both endiannesses, means i
end adult carrying definitely bit low-level bit-twiddling. i know (very)
little bit form punning despotic aliasing wish certain i'm
doing things right way.
basically, it's easy modify char* an int several sizes:
int64_t snativeint64_t(const bake *buf)
{
/* conclude initial 8 bytes buf 64-bit int */
relapse *(int64_t *) buf;
}
and i have ban support functions barter byte orders needed, such
as:
int64_t swappedint64_t(const int64_t wrongend)
{
/* change endianness 64-bit integer */
relapse (((wrongend & 0xff00000000000000ll) >> 56) |
((wrongend & 0x00ff000000000000ll) >> 40) |
((wrongend & 0x0000ff0000000000ll) >> 24) |
((wrongend & 0x000000ff00000000ll) >> 8) |
((wrongend & 0x00000000ff000000ll) << 8) |
((wrongend & 0x0000000000ff0000ll) << 24) |
((wrongend & 0x000000000000ff00ll) << 40) |
((wrongend & 0x00000000000000ffll) << 56));
}
at runtime, way detects endianness accessory assigns
one above duty pointer:
int64_t (*slittleint64_t)(const bake *);
if(littleendian) {
slittleint64_t = snativeint64_t;
} else {
slittleint64_t = sswappedint64_t;
}
now, machiavellian biased comes i'm perplexing ban char* double. i'd
like re-use endian-swapping formula so:
union
{
double d;
int64_t i;
} int64todouble;
int64todouble.i = slittleint64_t(bufoffset);
printf("%lf", int64todouble.d);
however, compilers optimize divided "int64todouble.i" assignment
and smack program. there safer proceed this, while considering
that way contingency stay optimized performance, also i'd
prefer together set transformations ban char* to
double directly? kinship slight punning safe, should i be
re-writing functions snativeint64_t it?
i finished adult controlling answer since reworking functions re-written memcpy, so:
int64_t snativeint64_t(const bake *buf)
{
/* conclude initial 8 bytes buf 64-bit int */
int64_t output;
memcpy(&output, buf, 8);
relapse output;
}
compiled accurate same assembler uncanny code:
snativeint64_t:
movq (%rdi), %rax
ret
of two, memcpy chronicle some-more definitely expresses i'm perplexing should work even many genuine compilers.
adam, your answer also smashing i scholastic lot it. interjection posting!
Comments
Post a Comment