长双精度与双精度

82

我知道不同的系统中,各种数据类型的大小可能会改变。

我使用 XP 32位,并使用 C++ 中的 sizeof() 运算符,看起来 long double 是 12 字节,double 是 8 字节。

然而,大部分可靠的来源都称 long double 是 8 字节,因此其范围与 double 相同。

为什么我的结果是 12 字节呢?如果 long double 确实是 12 字节,那么这是否也扩展了其值的范围?或者长标识符仅在值超出 double 范围时(编译器自动判断),才会扩展到 8 字节之外?


2
这是ISO C中最糟糕的特性。我强烈不建议您使用它。由于规范非常松散,它只会导致问题。 - Jeff Hammond
@JeffHammond 不能太严格,否则C如何能在12、16、24、36、60、72位系统上使用呢?你无法指定一个固定的IEEE-754浮点格式,在一个具有72位非IEEE浮点数的系统上高效运行。 - phuclv
3个回答

76

引用自维基百科

在x86架构上,大多数编译器将long double实现为该硬件支持的80位扩展精度类型(有时以12或16字节存储以保持数据结构)。

而且

编译器还可以使用128位四倍精度格式的long double,目前是通过软件实现的。

换句话说,是的,long double 可能能够存储比double更大范围的值。但这完全取决于编译器。


2
数据类型非常依赖于你所开发的体系结构。 - karlphillip
这也取决于编译器选项。在几乎所有的x86编译器上,80位类型都可以被明确禁用。 - greyfade
1
@karlphillip, @greyfade:是的,我只是指“由编译器决定”在它决定如何存储数据的意义上。显然,它受限于平台上可用的内容,当然编译器可以选择允许用户覆盖。 - Borealid
1
苹果声称 long double 是 128 位:https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/64bitPorting/transition/transition.html。 - Aaron Franke
3
@AaronFranke 这是填充后的大小。在x86上,实际基础类型仍为80位扩展格式,但会填充到12个字节,在x86-64上则会填充到16个字节,以便对齐。除了MSVC之外,几乎所有的x86编译器都会这样做。没有人会使用IEEE-754四倍精度来表示长双精度,因为那会非常慢。 - phuclv
1
@AaronFranke 这也是由x86-64 SysV ABI规定的,Unix(包括Apple)都在使用。只需检查LDBL_MANT_DIG并参见 https://news.ycombinator.com/item?id=19237884。 - phuclv

20

对于现代x64编译器,Clang和GCC使用16字节的双精度浮点数来表示long double类型,而VC++使用8字节的双精度浮点数。换句话说,使用Clang和GCC可以获得更高精度的双精度浮点数,但对于VC++来说,long doubledouble相同。现代x86 CPU确实支持这些16字节的双精度浮点数,因此我认为Clang和GCC做得很好,可以使用更高级别的语言基元访问低级硬件能力。


3
大小为16字节,但其中6字节是填充的。long double默认情况下始终为80位扩展,在x86和x86-64上分别填充为12/16字节。如果您愿意破坏ABI或某些API,则可以通过-mlong-double-64/80/128选项更改大小。还有-m96/128bit-long-double可更改填充大小。 - phuclv

5

数字的标准字节大小是在所有平台上保证的最小大小。它们在某些系统上可能会更大,但绝不会更小。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接