c++ - 使用 gcc 编译时 PowerPC 上的 long double 错误

标签 c++ gcc floating-point powerpc long-double

当我为 long double 变量类型赋值时,我遇到了一个奇怪的错误。 (PowerPC架构,gcc v4.9.2)

具体来说:

const constexpr long double DEGREE_TO_RAD = 0.0174532925199432954743716805978693;
const constexpr long double RAD_TO_DEGREE = 1. / DEGREE_TO_RAD;

似乎会导致以下编译器错误:

error: ‘(1.0e+0l / 1.74532925199432954743716805978693e-2l)’ is not a constant expression
 const constexpr long double RAD_TO_DEGREE = 1. / DEGREE_TO_RAD;

我不是 C++ 专家;这是我试图专门为我的开发机器环境构建的软件。然而,我的研究使我得到了以下花絮:

On some PowerPC and SPARCv9 machines, long double is implemented as a double-double arithmetic, where a long double value is regarded as the exact sum of two double-precision values, giving at least a 106-bit precision; with such a format, the long double type does not conform to the IEEE floating-point standard. Otherwise, long double is simply a synonym for double (double precision). [wiki]

这让我相信构建失败是由于 long double 在我的架构中与标准 x86 有不同的解释。将源代码中的 long double 更改为 double 可以使编译成功。这是巧合吗?在这种情况下,为什么 g++ 会对此大发雷霆?

最佳答案

这是与 constexpr 相关的错误(或可能是多个错误) . PowerPC 的 Clang does compile your snippet没有任何问题。如果你删除 constexpr然后 GCC 也在 C mode 中正确编译它和 C++ mode


关于bug,第一个issue可以从GCC的报错信息中看出

               ↓                                        ↓
error: ‘(1.0e+0l / 1.74532925199432954743716805978693e-2l)’ is not a constant expression
const constexpr long double RAD_TO_DEGREE = 1. / DEGREE_TO_RAD;

没有 L源文件中的后缀,但不知何故它出现在错误输出中。如果我通过添加后缀来更正代码,它仍然会因同样的原因而失败。我没有用于 PowerPC 的较新版本的 GCC,所以我无法验证这一点,但错误出现在 GCC 4.8.5 and 6.3.0, and even AT12.0 (which is based on GCC 8) on Compiler Explorer 中。

确实 PowerPC 使用了 double-double arithmetic对于 long double 默认情况下,但浮点格式只是对用户透明内部实现细节。它应该不会影响正确代码的编译。大多数嵌入式系统没有浮点支持,大多数当前平台没有 128 位硬件 long double .他们都使用软件来进行这些操作,但浮点代码仍然可以在它们上正常编译。无论格式如何,有效代码都应该编译并

如果我 specify -mabi=ieeelongdouble 它们确实有效尽管。在这里你也可以清楚的看到使用和不使用L的区别。后缀,因为没有它,文字是 double并将在 double build 转换为 long double 之前的精度,这意味着您将丢失 double 以外的所有数字。 如果不使用 double,请记住始终在浮点类型中使用正确的后缀

.LC0:    # 1./0.0174532925199432954743716805978693
        .long   1074055773
        .long   3248897055
        .long   2108954270
        .long   2705146754
.LC1:    # 1.L/0.0174532925199432954743716805978693L
        .long   1074055773
        .long   3248897055
        .long   2108954270
        .long   2705146739

other platforms 的常量相同使用 IEEE-754 quadruple-precision floating-point format

关于c++ - 使用 gcc 编译时 PowerPC 上的 long double 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48553127/

相关文章:

c - 为什么 scanf 对大 float 输入错误?

floating-point - 为什么浮点寄存器不同于通用寄存器

C++ - CreateThread - 编译错误

ubuntu - GCC 为获取和放置调用 __fn_chk,我怎样才能直接调用不安全的函数?

gdb 中的 C++ static_cast 返回与 gcc 不同的结果

c - 将存档链接到存档

python - pandas 方式将一天中的时间(有效 datetime.time)转换为浮点变量

c++ - 禁用调试错误?

c++ - 非捕获通用 lambda 应该衰减为函数指针吗?

c++ - 指向引用的指针或指向指针的引用