【问题标题】:Why isn't "0f" treated as a floating point literal in C++?为什么“0f”在 C++ 中不被视为浮点文字?
【发布时间】:2011-04-27 01:31:30
【问题描述】:

为什么 0f 在 C++ 中不被视为浮点字面量?

#include <iostream>

using namespace std;

int main(){
  cout << 0f << endl;

  return 0;
}

编译上面给了我

C2509(语法错误:'数字后缀错误')

使用 VS2008。

【问题讨论】:

  • “为什么”关于语言设计中任意小点的问题通常无法得到令人满意的回答。
  • @David - 谢谢,伙计。这是非常有用的信息。
  • @Vulcan:不幸的是,这已经提供了尽可能多的信息。您并没有比 Oli Charlesworth 和 Dakota Hawkins 在下面的答案更好,而且您对他们不满意。从根本上说,您是在询问三十多年前在 C 语法中做出一个小决定的原因。很可能没有明确的原因。
  • 很难理解为什么这个问题有 6 票反对。这是一个很好的问题,可以深入了解解析器和扫描器的工作原理。
  • @coaddict:我认为它不应该被否决,但与此同时,我认为我们没有学到任何关于解析器的有趣之处!它只是一个任意的语言规范,在实践中没有任何影响。

标签: c++ syntax floating-point syntax-error notation


【解决方案1】:

因为 0 是一个整数常量。

edit:codepad.org(假设为g++)给出的错误信息可能更容易理解一些。 “错误:整数常量上的后缀“f”无效”。 “0.f”会起作用,因为 0.(或 0.0,同样的东西)是一个十进制常量,并且要求一个十进制常量是一个浮点数比要求一个整数常量是一个浮点数更有意义 :)

【讨论】:

  • @Dakota,这正是我添加“f”后缀以强制编译器将其视为浮点数的原因。
  • f 只能应用于 double 字面量(如 0.0),0 是 int 字面量。
  • @Etienne,问题是为什么?
  • 那么我想你的答案是“因为它就是这样工作的”。编译器以不同的方式处理整数常量和十进制常量。 0.0 本身就是双精度数,因此您可以添加“f”以使其成为浮点数。 0 本身将是一个整数,浮点后缀不适用。同样,“0.0UL”可能不会编译。
  • @Vulcan Eager:为什么真的重要吗?重要的是询问为什么要索引您使用 [] 而不是 的数组,或者为什么程序的入口点是一个名为 main 而不是 StartHere 的函数。除了'因为标准这么说之外,没有其他原因
【解决方案2】:

因为你需要0.0f。

【讨论】:

  • 我知道 0.0f 会使编译器静音。但这仍然不能解释为什么单独的“f”后缀不能解决问题。
  • @Vulcan:大概,“只是因为”。基本上,我赞同上面大卫·索内利的观点。
【解决方案3】:

假设 C++ 用于浮点常量的语法与 C 相同(我认为这是正确的),我们有:

取自ANSI C grammar的一些快捷方式的定义

D      [0-9]
L      [a-zA-Z_]
H      [a-fA-F0-9]
E      [Ee][+-]?{D}+
FS     (f|F|l|L)
IS     (u|U|l|L)*

现在您在浮点末尾看到的f 或F 已在上面的FS 中定义。

现在让我们看看识别有效浮点常量的语法:

{D}+{E}{FS}?        
{D}*"."{D}+({E})?{FS}?  
{D}+"."{D}*({E})?{FS}?  

现在,如果您仔细观察,没有任何规则可以识别 0f。

使用 rule1 我们可以得到0e0f

使用 rule2 我们可以得到.0f 或0.0f

使用 rule3 我们可以得到0.f 或0.0f

在您的情况下实际发生的是 0f 的 0 将被词法分析器作为整数常量 D 使用,f 将作为 FS 令牌使用。现在,当解析看到 D 后跟 FS 没有匹配规则时,它会吐出错误:

error: invalid suffix "f" on integer constant

【讨论】:

    【解决方案4】:

    如果此设计决定有明确说明的原因,则应在 C99“基本原理”文档中(C++ 从 C 中逐字复制所有这些内容,而没有重新考虑)。但是没有。这就是关于“f”后缀的所有内容:

    §6.4.4.2 浮动常量

    与现有实践一致,浮点常量定义为 输入 double。由于 C89 允许表达式仅包含 float 操作数 在 float 算术而不是 double 中执行,这是一种 表达明确的 float 常量是可取的。 long double 类型 引发了类似的问题。

    添加了 F 和 L 后缀来传达类型信息 浮动常量,很像 L 后缀对长整数的作用。默认 为了与先前的做法兼容,浮动常量的类型保持为 double。 小写 f 和 l 也可以作为后缀。

    不过,是一个隐含的原因。请注意措辞:“已添加 ... 后缀以使用浮动常量传达类型信息。”该标准的作者认为数字常量在您到达后缀时已经明确地是整数或浮点数。后缀仅用于类别内的额外特异性,它不能将数字从一个类别翻转到另一个类别。这得到了实际语法(C99 §6.4.4)的支持,该语法首先将数字常量定义为整数常量或浮点常量,然后定义单独的类每个的后缀。

    【讨论】:

    • +1。这是唯一真正提供此决定背后可能的基本原理的答案。
    【解决方案5】:

    这里有一个“因为”:如果带有f 后缀的int 常量自动转换为float,那么0x0f 将是不明确的。

    【讨论】:

    • 不一定;在没有p+EXP 或p-EXP 后缀的情况下,0x 后缀已被视为强制整数(即0x0.0 是语法错误); 0x0.0p+0f 没有歧义,因为即使尾数是十六进制,指数也是十进制的。然而,这仍然是一个很好的观点,很可能已经在委员会成员的脑海中。
    【解决方案6】:

    这不一定是唯一的原因,但l 或L 后缀可以应用于整数文字或浮点文字。 42L 是 long int 类型; 42.0L 的类型为 long double。

    必须消除带有L 后缀的数字文字,以确定它是整数还是浮点数。允许 F 后缀本身来确定文字的类型将是不一致的并且可能会造成混淆。这也会使在该语言的未来版本中添加新后缀变得更加困难。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-11
      • 2020-07-28
      • 1970-01-01
      • 2014-01-21
      • 2010-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多