Ich versuche, die Bits aus einem Float zu extrahieren, ohne undefiniertes Verhalten aufzurufen. Hier ist mein erster Versuch:float bits und striktes Aliasing
unsigned foo(float x)
{
unsigned* u = (unsigned*)&x;
return *u;
}
Wie ich es verstehe, ist dies nicht wegen der strengen Aliasing Regeln garantiert arbeiten, nicht wahr? Funktioniert es, wenn ein Zwischenschritt mit einem Zeichenzeiger gemacht wird?
unsigned bar(float x)
{
char* c = (char*)&x;
unsigned* u = (unsigned*)c;
return *u;
}
Oder muss ich die einzelnen Bytes selbst extrahieren?
unsigned baz(float x)
{
unsigned char* c = (unsigned char*)&x;
return c[0] | c[1] << 8 | c[2] << 16 | c[3] << 24;
}
Natürlich hat dies den Nachteil auf endianness von je, aber ich konnte damit leben.
Der Union Hack ist definitiv undefiniert Verhalten, oder?
unsigned uni(float x)
{
union { float f; unsigned u; };
f = x;
return u;
}
Nur der Vollständigkeit halber, hier ist eine Referenzversion von foo
. Auch undefiniertes Verhalten, oder?
unsigned ref(float x)
{
return (unsigned&)x;
}
So ist es möglich, die Bits von einem Schwimmer zu extrahieren (vorausgesetzt, beide sind 32 Bit breit, natürlich)?
EDIT: Und hier ist die memcpy
Version wie von Goz vorgeschlagen. Da viele Compiler noch nicht static_assert
unterstützen, habe ich static_assert
mit etwas Metaprogrammierung ersetzt:
template <bool, typename T>
struct requirement;
template <typename T>
struct requirement<true, T>
{
typedef T type;
};
unsigned bits(float x)
{
requirement<sizeof(unsigned)==sizeof(float), unsigned>::type u;
memcpy(&u, &x, sizeof u);
return u;
}
ich mit dem ersten Ansatz ein Problem nicht wirklich sehen, hat - Sie nicht einmal haben zwei Zeiger, die auf dasselbe Objekt zeigen. Sie sollten in Ordnung sein, obwohl Sie eine Kompilierungszeit behaupten möchten, dass sizeof (float) == sizeof (unsigned). Ich sehe auch kein Problem mit dem Gewerkschafts-Hack (obwohl ich die Größe erneut überprüfen würde). Aber ich bin sicher, dass es einige obskure Regeln gibt, die mir nicht bewusst sind. Lasst uns zurücklehnen und darauf warten, dass die Leute mir beweisen, dass ich falsch liege! – EboMike
@Ebomike: Die erste Methode stört die strengen Aliasing-Regeln. Haben Sie einen Lese dafür: http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html – Goz
Danke, wusste ich, mich jemand falsch erweisen würde :) – EboMike