問題描述
什么是 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.)
這篇關于陷阱表示的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!