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

19

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

#include <iostream>

using namespace std;

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

  return 0;
}

编译上述代码出现以下错误:

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

使用VS2008。


6
通常无法令人满意地回答有关语言设计中小而随意的点的“为什么”问题。 - David Thornley
2
@David - 谢谢,伙计。非常有启发性。 - Agnel Kurian
12
很遗憾,这就是所有的信息了。你不会得到比Oli Charlesworth和Dakota Hawkins在下面提供的答案更好的答案,而且你对它们也不满意。基本上,你正在询问C语法中一个小决定背后的原因,而这个决定已经做出了三十多年。很可能当时并没有明确的原因。 - David Thornley
1
很难理解为什么这个问题有6个踩。这是一个好问题,可以让人了解解析器和扫描器的工作原理。 - codaddict
1
@Vulcan:你能给我一个反例吗? - Oliver Charlesworth
显示剩余2条评论
6个回答

24
如果这个设计决策有一个明确的声明原因,它会在C99 “Rationale”文件中说明(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)支持这一点,它首先将数字常量定义为整数常量或浮点常量,然后为每个类别定义单独的后缀类别。

4
这是唯一一个真正提供了这个决定背后可能原因的线索的答案。 - Brian

20

假设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)*

现在你看到浮点数结尾处的fF是在上方定义的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

15

因为 0 是一个整数常量。

编辑:codepad.org(假设是g ++)给出的错误消息可能更容易理解。 "error: invalid suffix" f "on integer constant"。 "0.f" 将起作用,因为 0. (或 0.0,同样的事情)是一个十进制常量,并且要求将十进制常量转换为浮点数比要求将整数常量转换为浮点数更有意义 :)


2
@Dakota,这正是我添加“f”后缀的原因,以便强制编译器将其视为浮点数。 - Agnel Kurian
f 只能应用于双精度字面量(例如 0.0),而 0 是整型字面量。 - Etienne de Martel
@Etienne,问题是为什么? - Agnel Kurian
嗯,因为标准这么说?我知道这是个烂答案,但我想不出其他原因了。 - Etienne de Martel
1
那么我想你的答案是“因为它就是这样工作的”。编译器会区别对待整数常量和十进制常量。单独的0.0将被视为double,因此您可以添加“f”以使其成为float。单独的0将被视为整数,并且浮点后缀不适用。同样,“0.0UL”可能无法编译。 - Dakota Hawkins
11
@Vulcan Eager:真的很重要吗?它之所以重要,就像问为什么要使用[]而不是<>来索引数组,或者为什么程序的入口点是一个名为“main”的函数而不是“StartHere”。没有其他原因,只因为标准规定如此。 - David Rodríguez - dribeas

11

因为你需要 0.0f


1
我知道0.0f可以让编译器静默。但这仍然无法解释为什么仅仅使用'f'后缀就不起作用。 - Agnel Kurian
@Vulcan:可能只是因为这样。基本上,我赞同David Thornely上面的观点。 - Oliver Charlesworth

3
这里有一个因素:如果带 f 后缀的 int 常量自动转换为 float,那么 0x0f 就会存在歧义。

1
不一定;在没有 p+EXPp-EXP 后缀的情况下,0x 后缀已经被视为强制整数(即 0x0.0 是语法错误);虽然尾数是十六进制,但指数是十进制,因此 0x0.0p+0f 没有歧义。然而,这仍然是一个很好的观点,可能已经存在于委员会成员的思想中。 - zwol

0

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

带有L后缀的数字文字必须进行歧义消解,以确定其是整数还是浮点数。仅凭F后缀来确定文本的类型可能会出现不一致和潜在的混淆。这也会使将来语言版本中添加新的后缀变得更加困难。


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