陷阱表示
什么是 C 中的陷阱表示"(一些示例可能会有所帮助)?这适用于 C++ 吗?
What is a "trap representation" in C (some examples might help)? Does this apply to C++?
鉴于此代码...
float f=3.5;
int *pi = (int*)&f;
... 并假设 sizeof(int) == sizeof(float)
,f
和 *pi
是否具有相同的二进制表示/模式?
... and assuming that sizeof(int) == sizeof(float)
, do f
and *pi
have the same binary representation/pattern?
推荐答案
陷阱表示是 C99(IIRC 不是 C89)使用的一个包罗万象的术语,用于描述适合类型占用的空间的位模式,但如果用作该类型的值,则会触发未定义的行为.定义在 6.2.6.1p5 节(所有 6.2.6 都有触角),我不打算在这里引用它,因为它又长又混乱.存在这种位模式的类型被称为具有"陷阱表示.没有类型需要有任何陷阱表示,但标准保证不有陷阱表示的唯一类型是
unsigned char
(6.2.6.1p5, 6.2.6.2p1).
A trap representation is a catch-all term used by C99 (IIRC not by C89) to describe bit patterns that fit into the space occupied by a type, but trigger undefined behavior if used as a value of that type. The definition is in section 6.2.6.1p5 (with tentacles into all of 6.2.6) and I'm not going to quote it here because it's long and confusing. A type for which such bit patterns exist is said to "have" trap representations. No type is required to have any trap representations, but the only type that the standard guarantees will not have trap representations is
unsigned char
(6.2.6.1p5, 6.2.6.2p1).
该标准给出了陷阱表示的两个假设示例,这两个示例都与任何真实 CPU 多年来所做的任何事情都不对应,因此我不会将您与它们混淆.陷阱表示的好示例(也是您可能遇到的任何 CPU 上的唯一硬件级陷阱表示)是浮点型.C99 附件 F(第 2.1 节)明确未定义信号 NaN 的行为,尽管 IEC 60559 详细规定了它们的行为.
The standard gives two hypothetical examples of trap representations, neither of which correspond to anything that any real CPU has done for many years, so I'm not going to confuse you with them. A good example of a trap representation (also the only thing that qualifies as a hardware-level trap representation on any CPU you are likely to encounter) is a signaling NaN in a floating-point type. C99 Annex F (section 2.1) explicitly leaves the behavior of signaling NaNs undefined, even though IEC 60559 specifies their behavior in detail.
值得一提的是,虽然允许指针类型具有陷阱表示,但空指针不是陷阱表示.空指针只有在被取消引用或偏移时才会导致未定义的行为;对它们的其他操作(最重要的是,比较和复制)是明确定义的.如果您只是使用具有陷阱表示的类型读取它们,则陷阱表示会导致未定义的行为.(是否无效但非空指针被视为或应该被视为陷阱表示是一个有争议的话题.CPU 不会那样对待它们,但编译器可能会.)
It's worth mentioning that, while pointer types are allowed to have trap representations, null pointers are not trap representations. Null pointers only cause undefined behavior if they are dereferenced or offset; other operations on them (most importantly, comparisons and copies) are well-defined. Trap representations cause undefined behavior if you merely read them using the type that has the trap representation. (Whether invalid but non-null pointers are, or should be, considered trap representations is a subject of debate. The CPU doesn't treat them that way, but the compiler might.)
您展示的代码具有未定义的行为,但这是因为指针别名规则,而不是因为陷阱表示.这是如何将 float
转换为具有相同表示的 int
(假设,如您所说,sizeof(float) == sizeof(int)代码>)
The code you show has undefined behavior, but this is because of the pointer-aliasing rules, not because of trap representations. This is how to convert a float
into the int
with the same representation (assuming, as you say, sizeof(float) == sizeof(int)
)
int extract_int(float f)
{
union { int i; float f; } u;
u.f = f;
return u.i;
}
这段代码在 C99 中有未指定(非未定义)行为,这基本上意味着标准没有定义产生什么整数值,但你确实得到了some 有效的整数值,它不是陷阱表示,并且不允许编译器在您没有这样做的假设下进行优化.(第 6.2.6.1 节,第 7 段.我的 C99 副本可能包含技术勘误――我记得这在原始出版物中未定义,但在 TC 中更改为未指定.)
This code has unspecified (not undefined) behavior in C99, which basically means the standard doesn't define what integer value is produced, but you do get some valid integer value, it's not a trap representation, and the compiler is not allowed to optimize on the assumption that you have not done this. (Section 6.2.6.1, para 7. My copy of C99 might include technical corrigienda ― my recollection is that this was undefined in the original publication but was changed to unspecified in a TC.)
相关文章