当我为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 ++专家;这是我试图专门为我的开发机器环境构建的软件。但是,我的研究让我想到了以下几点:
在某些PowerPC和SPARCv9机器上,
long double
实现为双倍算术,其中long double
值被视为两个双精度值的精确总和,至少给出106位精度;对于这种格式,long double
类型不符合IEEE浮点标准。否则,long double
只是double
的同义词(双精度)。 [wiki]
这让我相信构建失败是由于我的架构与标准x86有不同的解释。在源中将long double
更改为double
可以使编译成功。这是巧合吗?为什么g ++会在这个实例中抛出它?
答案 0 :(得分:0)
这是一个错误(或多个错误)。可以从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 was based on GCC) on Compiler Explorer
Indeed PowerPC默认将double-double arithmetic用于long double
,但是浮点格式只是对用户透明的内部实现细节。它应该不影响正确代码的编译。大多数嵌入式系统没有浮点支持,并且大多数当前平台都没有用于128位long double
的硬件。他们都使用软件进行这些操作,但是浮点代码仍然可以很好地进行编译。因此,无论采用哪种格式,都应编译有效的代码,然后Clang for PowerPC does compile your snippet
如果我specify -mabi=ieeelongdouble
,它们确实可以工作。在这里,您还可以清楚地看到使用和不使用后缀L
的区别,因为如果没有后缀,则文字是double
,在转换为{{1之前,将被截断为double
精度。 }},这意味着您将失去双精度以外的所有数字。请记住,如果您不使用long double
double
使用other platforms的IEEE-754 quadruple-precision floating-point format常量是相同的