J'essaie d'extraire les bits d'un flottant sans invoquer de comportement indéfini. Voici ma première tentative:bits flottants et aliasing strict
unsigned foo(float x)
{
unsigned* u = (unsigned*)&x;
return *u;
}
Si je comprends bien, cela est pas garanti en raison des règles strictes d'aliasing, non? Est-ce que cela fonctionne si vous prenez une étape intermédiaire avec un pointeur de caractère?
unsigned bar(float x)
{
char* c = (char*)&x;
unsigned* u = (unsigned*)c;
return *u;
}
Ou dois-je extraire moi-même les octets individuels?
unsigned baz(float x)
{
unsigned char* c = (unsigned char*)&x;
return c[0] | c[1] << 8 | c[2] << 16 | c[3] << 24;
}
Bien sûr, cela a l'inconvénient de dépendre de l'endianness, mais je pourrais vivre avec cela.
Le hack de l'union est certainement un comportement indéfini, non?
unsigned uni(float x)
{
union { float f; unsigned u; };
f = x;
return u;
}
Juste pour être complet, voici une version de référence de foo
. Aussi un comportement indéfini, non?
unsigned ref(float x)
{
return (unsigned&)x;
}
Alors, est-il possible d'extraire les bits d'un flotteur (si les deux sont très, bien sûr 32 bits)?
EDIT: Et voici la version memcpy
proposée par Goz. Étant donné que de nombreux compilateurs ne supportent pas encore static_assert
, je l'ai remplacé static_assert
avec quelques métaprogrammation modèle:
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;
}
je ne vois pas vraiment un problème avec la première approche - vous n'avez même pas deux pointeurs pointant vers le même objet. Cela devrait aller, même si vous voulez un temps de compilation affirmer que sizeof (float) == sizeof (unsigned). Je ne vois pas non plus de problème avec le hack de l'union (bien que je vérifierais encore la taille). Mais je suis sûr qu'il y a des règles obscures que je ne connais pas. Asseyons-nous et attendons que les gens me prouvent le contraire! – EboMike
@Ebomike: La première méthode tombe sous le coup des règles strictes d'aliasing. Avoir une lecture de ceci: http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html – Goz
Merci, je savais que quelqu'un me prouverait faux :) – EboMike