Question d'un juriste linguiste. D'accord.
Mon top 3 personnel :
-
violation de la règle stricte de l'aliasing
-
violation de la règle stricte de l'aliasing
-
- violation de la règle stricte de l'aliasing
-)
Editer Voici un petit exemple qui se trompe deux fois :
(en supposant qu'il s'agit d'ints 32 bits et de little endian)
float funky_float_abs (float a)
{
unsigned int temp = *(unsigned int *)&a;
temp &= 0x7fffffff;
return *(float *)&temp;
}
Ce code tente d'obtenir la valeur absolue d'un flottant en jouant sur le bit de signe directement dans la représentation d'un flottant.
Cependant, le résultat de la création d'un pointeur sur un objet en passant d'un type à un autre n'est pas valide en C. Le compilateur peut supposer que des pointeurs de types différents ne pointent pas vers le même morceau de mémoire. Ceci est vrai pour tous les types de pointeurs sauf void* et char* (le signe n'a pas d'importance).
Dans le cas ci-dessus, je le fais deux fois. Une fois pour obtenir un int-alias pour le float a, et une fois pour reconvertir la valeur en float.
Il existe trois façons valables de procéder.
Utiliser un pointeur char ou void lors de la conversion. Ces pointeurs sont toujours des alias de n'importe quoi, ils sont donc sûrs.
float funky_float_abs (float a)
{
float temp_float = a;
// valid, because it's a char pointer. These are special.
unsigned char * temp = (unsigned char *)&temp_float;
temp[3] &= 0x7f;
return temp_float;
}
Utiliser memcopy. Memcpy prend des pointeurs de type void, ce qui force également l'aliasing.
float funky_float_abs (float a)
{
int i;
float result;
memcpy (&i, &a, sizeof (int));
i &= 0x7fffffff;
memcpy (&result, &i, sizeof (int));
return result;
}
Troisième solution valable : utiliser les unions. Il s'agit explicitement d'une pas indéfini depuis C99 :
float funky_float_abs (float a)
{
union
{
unsigned int i;
float f;
} cast_helper;
cast_helper.f = a;
cast_helper.i &= 0x7fffffff;
return cast_helper.f;
}
4 votes
foo(c++, c)
yfoo(++c, c)
sont tous deux comportement non défini qui l'emporte complètement sur le non spécifié.