以"E"结尾时减去十六进制常数的错误


int main()
{
0xD-0; // Fine
0xE-0; // Fails
}

第二行在clang和gcc上都无法编译。任何其他十六进制常量结尾都可以(0-9,A-D, F)。

错误:

<source>:4:5: error: unable to find numeric literal operator 'operator""-0'
4 |     0xE-0;
|     ^~~~~

我有一个修复(在常量之后和减法之前添加一个空格),所以我主要想知道为什么?这和它认为这里有一个指数有关吗?

https://godbolt.org/z/MhGT33PYP

实际上,这种行为是c++标准强制要求的(并且有文档记录),尽管看起来很奇怪。这是因为c++是如何使用预处理令牌(又名pp-tokens)进行编译的。

如果我们仔细观察编译器如何为数字生成token:

预处理数字由一个数字组成,前面可以有一个句号,后面可以有字母、下划线、数字、句点和e+ e- e+ e-中的任意一种。

根据此,编译器读取0x,然后E-,它将其解释为数字的一部分,因为在数字pp-令牌中允许有E-,并且在E-之间没有空格(这就是为什么添加空格是一个简单的修复)。

这意味着0xE-0被接收为单个预处理标记。换句话说,编译器将其解释为一个数字,而不是两个数字0xE0以及一个操作-。因此,编译器期望E表示浮点数字面量的指数。

现在让我们看一下c++是如何解释浮点量的。请看"例子"下面的部分。它给这个奇怪的代码示例:

<< "n0x1p5         " << 0x1p5        // double
<< "n0x1e5         " << 0x1e5        // integer literal, not floating-point

E被解释为整数字面值的一部分,并且不是使数字为十六进制浮点文字!因此,编译器将0xE识别为单个十六进制整数。然后是-0,它在技术上属于同一预处理令牌的一部分,因此不是操作符和另一个整数。哦哦。现在无效,因为没有-0后缀。

因此编译器报告一个错误,如下所示

相关内容

  • 没有找到相关文章

最新更新