Bur*_*urt 63 c c++ gcc visual-studio-2010
什么是C中的陷阱表示(某些示例可能有帮助)?这适用于C++吗?
float f=3.5;
int *pi = (int*)&f;
Run Code Online (Sandbox Code Playgroud)sizeof(int) == sizeof(float)do f和*pi具有相同的二进制表示/模式?MSVC怎么样?zwo*_*wol 95
陷阱表示是C99(IIRC而不是C89)用来描述适合类型占用空间的位模式的全部术语,但如果用作该类型的值,则触发未定义的行为.定义见6.2.6.1p5(6.2.6中的所有内容都有触角),我不打算在这里引用它,因为它很长而且令人困惑.存在这种位模式的类型被称为"具有"陷阱表示.没有类型需要任何陷阱表示,但标准保证不具有陷阱表示的唯一类型是unsigned char(6.2.6.1p5,6.2.6.2p1).
该标准给出了陷阱表示的两个假设示例,这两个示例都不对应任何真实CPU多年来所做的任何事情,因此我不会将您与它们混淆.陷阱表示的一个很好的例子(也是唯一可以作为您可能遇到的任何CPU上的硬件级陷阱表示的东西)是浮点类型的信令NaN.C99附件F(第2.1节)明确地将信令NaN的行为定义为未定义,即使IEC 60559详细说明了它们的行为.
值得一提的是,当指针类型都允许有陷阱表示,空指针是不是陷阱表示.如果取消引用或偏移,则空指针仅导致未定义的行为; 对它们的其他操作(最重要的是,比较和复制)是明确定义的.如果仅使用具有陷阱表示的类型读取陷阱表示,则陷阱表示会导致未定义的行为.(无效但非空指针是否应该被认为是陷阱表示是一个争论的主题.CPU不会这样对待它们,但编译器可能会.)
您显示的代码具有未定义的行为,但这是因为指针别名规则,而不是因为陷阱表示.这是如何将a float转换为int具有相同的表示(假设,如你所说sizeof(float) == sizeof(int))
int extract_int(float f)
{
union { int i; float f; } u;
u.f = f;
return u.i;
}
Run Code Online (Sandbox Code Playgroud)
此代码在C99中具有未指定(未定义)的行为,这基本上意味着标准不定义生成的整数值,但是您确实获得了一些有效的整数值,它不是陷阱表示,并且不允许编译器进行优化假设你还没有这样做.(6.2.6.1节,第7,我的C99的副本可能包括技术corrigienda -我的回忆是,这是在原来的出版物不确定,但改为不确定的TC).
使用指向int的别名浮点数的未定义行为.
一般来说,任何非陷阱 IEEE-754 浮点值都可以在某些平台上表示为整数,没有任何问题。但是,如果您假设所有浮点值都具有唯一的整数表示形式并且碰巧强制FPU加载该值,则某些浮点值可能会导致意外行为。
(该示例取自字节交换浮点类型。)
例如,在处理浮点数据时,您需要在具有不同字节顺序的 CPU 之间进行封送,您可能会考虑执行以下操作:
double swap(double)
不幸的是,如果编译器将输入加载到 FPU 寄存器中并且它是陷阱表示形式,则 FPU 可以使用恰好是不同位表示形式的等效陷阱表示形式将其写回。
换句话说,如果您没有正确转换(我所说的正确是指通过union、memcpyviachar *或其他标准机制),有些浮点值将没有相应的位表示形式。
| 归档时间: |
|
| 查看次数: |
12301 次 |
| 最近记录: |