-
Qu'est-ce que la représentation d'un piège en C (quelques exemples pourraient aider)? Est-ce que cela s'applique au C ++?
float f=3.5; int *pi = (int*)&f;
- Edit: Je sais que 'pi' viole la règle de crénelage et qu’il correspond à UB selon la norme C. Au moins sur GCC, il ne produit aucune erreur, mais des avertissements. Dans cette implémentation (c'est-à-dire, GCC), en supposant que
sizeof(int) == sizeof(float)
%%f
et*pi
ont la même représentation / modèle binaire? Qu'en est-il de MSVC?
Réponses
Trop de publicités?-
Un piège de la représentation est un fourre-tout terme utilisé par C99 (IIRC pas en C89) pour décrire les modèles de bits qui s'inscrivent dans l'espace occupé par un type, mais de déclencher un comportement indéfini si elle est utilisée comme une valeur de ce type. La définition est dans la section 6.2.6.1p5 et je ne vais pas citer ici, car il est long et confus. Un type pour lequel de tels modèles de bits existent est dit "avoir" piège des représentations. Tout type (sauf
unsigned char
) peut avoir piège des représentations, mais pas de type est nécessaire de les avoir. La norme ne parle que de deux piège des représentations: logiciel-visible des bits de parité sur les types numériques, et "négatif zéro" non-deux-compléter les architectures. Autant que je sache, personne n'a fabriqué un CPU qui ne soit de ces choses dans de nombreuses années, et le C de la norme en continuant à fournir en vue de leur éventuelle existence est une sorte de bête. Un meilleur exemple à mon humble avis serait à virgule flottante IEEE de signalisation NaNs, dont le comportement n'est pas défini explicitement par le C99 (annexe F, section 2.1), même si il est précisé en détail dans la norme IEC 60559.Il vaut probablement la peine de mentionner que d'un pointeur null est pas un piège de la représentation d'un type de pointeur. Pointeurs Null seulement provoquer un comportement non défini si ils sont déréférencés ou offset, d'autres opérations sur les pointeurs null (plus important encore, les comparaisons et les copies) sont bien définis. Piège des représentations provoquer un comportement non défini si vous ne lisez - le en utilisant le type qui a le piège de la représentation.
-
Le code vous montrer a un comportement indéfini, mais c'est parce que le pointeur de-aliasing règles, non pas à cause du piège des représentations. C'est la façon de convertir un
float
dans laint
avec la même représentation (en supposant, comme vous le dites,sizeof(float) == sizeof(int)
)int extract_int(float f) { union { int i; float f; } u; u.f = f; return u.i; }
Ce code a indéterminée (et non pas défini) comportement en C99, qui signifie en gros que la norme ne définit pas ce qu'valeur entière est produit, mais vous n'obtenez pas certaines entier valide, il n'est pas un piège de la représentation, et le compilateur n'est pas autorisé à optimiser sur l'hypothèse que vous ne l'avez pas fait. (Section 6.2.6.1, paragraphe 7. Ma copie de C99 peut inclure des techniques corrigienda - mon souvenir est que ce n' était pas défini dans la publication originale, mais a été changé à précisées dans un TC.)
En général, tous les non-trap IEEE-754 valeur à virgule flottante peut être représentée par un entier sur certaines plates-formes sans aucun problème. Cependant, il y a des valeurs à virgule flottante qui peut entraîner un comportement inattendu si l'on suppose que toutes les valeurs à virgule flottante ont un entier unique de représentation et de vous arriver, à force de la FPU pour charger cette valeur.
(Exemple tiré d' http://www.dmh2000.com/cpp/dswap.shtml)
Par exemple, lorsque vous travaillez avec des FP données dont vous avez besoin pour le maréchal entre les Processeurs avec différents endianness, vous pourriez penser de la manière suivante:
double swap(double)
Malheureusement, si le compilateur charge l'entrée dans une FPU s'inscrire et c'est un piège de la représentation, le FPU peut l'écrire avec un équivalent piège de la représentation qui se trouve être une autre représentation binaire.
En d'autres termes, il y a quelques FP valeurs qui n'ont pas un bit correspondant de la représentation si vous ne vous convertissez pas correctement (par la bonne, je veux dire par le biais d'un union
, memcpy
par char *
ou d'un autre mécanisme standard).