19

语言设计者选择在以下场景中使用花括号:

if (a)
    b
while (a)
    b
...

为什么在函数中不允许相同,像这样?

int add(int a, int b)
    return a + b;
4

6 回答 6

27

我敢肯定这会弄乱语法。例如,这个空函数定义之间没有区别......

void empty()
{
    ;
}

...和这个函数声明:

void empty();
于 2012-10-23T16:00:25.877 回答
6

我不确定他们是否“选择”了这个。相反,省略花括号 for if、while、for 等的能力是它们指定语法的方式的自然结果。语法禁止它用于函数可能是因为旧式函数声明。

于 2012-10-23T15:55:12.593 回答
3

没有与函数定义相关的固定关键字。使用if/ else/ for/ while/switch有一个这样的关键字,标志着逻辑控制结构的开始。

尽管上下文允许我们人类辨别int some_name (some_expression) some_other_expressions;函数是如何产生的 - 在编程实践中(尽管明确可行)需要大量回溯才能确保令牌流中前面的 3-4-6 个符号没有任何改变函数声明的情况到别的东西。

编程语言解析器可以通过它的解析方法进行分类,要么它获取令牌列表中的当前令牌并检查下一个令牌是否确认“这是一个 if”或“这是一个函数”,或者它需要最大的查找 -提前标记(2-3-6?)并确认“这可能是一个函数”,“现在我看到第 5 个标记这肯定是一个函数”,或者它使用带有可变前瞻方法的回溯根据需要在令牌列表中,以确保我们正在研究的构造不是别的东西。

于 2012-10-23T15:58:12.300 回答
2

如果我推测,我会说这是因为一个函数通常包含多个语句,而 if 或 while 语句通常只包含一个语句。此外,它被证明是有远见的,因为在 C++ 中允许省略 {} 会导致成员函数中的歧义。例如:

struct s
{
     void f() const int i; //does const refer to int i or the function?
}
于 2012-10-23T15:53:53.177 回答
1

花括号不是“if”和“if-else”控制语句的可选组件。“if”控制语句的语法产生式允许一个非终结符跟在表达式后面。“if-else”控制语句的语法产生式允许一个非终结符跟在表达式之后,一个非终结符跟在“else”终结符之后。该非终结符的名称是 <statement>。

在控制结构(又名控制语句)的上下文中,花括号属于称为 <compound-statement>(有时称为 <block>)的语言非终结符符号。非终结符 <compound-statement> 出现在 <statement> 语法产生式的右侧,这就是为什么花括号可以与“if”和“if-else”控制语句一起使用(即,复合语句是一个语句)。

<statement> ::= <if-then-statement> | 
                <if-then-else-statement> | 
                <for-statement> |
                <do-while-statement> |
                ...
                <compound-statement>

<statement-list> ::=  <statement> | <statement-list> <statement> 

<if-then-statement> ::= "if" "(" <expression> ")" <statement> 

<if-then-else statement> ::= "if" "(" <expression> ")" <statement> 'else' <statement>

<compound-statement> ::= "{" <statement-list> "}"

对于函数声明,<compound-statement> 非终结符是 <function-declaration> 语法产生式右侧的最后一个非终结符。

PS 所有非终结符都是语法产生。所有语法产生式都简化为一个或多个非终结符号和/或终结符号。终端符号是语言关键字。

于 2013-02-19T20:28:20.227 回答
1

我知道这就像一个 7 年的颠簸,但以上所有答案都不正确;尽管罗伯特库珀说这会破坏语法是正确的。

真正的问题与 C 的原始版本的外观有关:

main(argc, argv)
    char *argv[];
{
    puts("hello world!");
}

默认情况下,C 中的所有内容都是 int,因此可以省略很多类型注释。Modern C 完全向后兼容,因为人们不想丢弃或更新一堆现有代码。

请注意,函数参数列表之后的类型注释看起来与普通变量声明完全一样。这是故意这样做的,可能是为了简化原始语法,但这意味着尝试定义一个没有花括号的函数,就像在你的例子中那样,将是完全模棱两可的。

基本上,它不能工作,因为解析器无法区分声明语句和类型注释之间的区别。

于 2020-02-04T03:28:12.703 回答