为什么函数中的花括号在C风格的语言中不是可选的?

时间:2012-10-23 15:51:05

标签: c

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

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

为什么函数中不允许这样的内容,比如这个?

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

6 个答案:

答案 0 :(得分:25)

我确信这会弄乱语法。例如,这个空函数定义......

之间没有区别
void empty()
{
    ;
}

...和这个函数声明:

void empty();

答案 1 :(得分:5)

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

答案 2 :(得分:3)

没有与功能定义相关的固定关键字。使用if / else / for / while / switch,有一个此类关键字标记逻辑控制结构的开头。

尽管上下文允许我们人类辨别出int some_name (some_expression) some_other_expressions;是一个函数 - 在编程实践中(虽然可以明确地做到)但需要大量的回溯来确保令牌中的3-4-6个符号 - stream没有任何东西将它从函数声明改为其他东西。

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

答案 3 :(得分:2)

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

struct s
{
     void f() const int i; //does const refer to int i or the function?
}

答案 4 :(得分:1)

大括号不是“if”和“if-else”控制语句的可选组件。 “if”控制语句的语法生成允许一个非终结符号跟随表达式。 “if-else”控制语句的语法生成允许一个非终结符号跟随表达式,一个非终结符号遵循“else”终止符号。该非终结符号的名称是< statement>。

在控制结构(a.k.a。控制语句)的上下文中,花括号属于称为< 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> "}"

关于函数声明,&lt; compound-statement&gt;非终结符号是&lt; function-declaration&gt;右侧的最后一个非终结符号。语法生产。

P.S。所有非终结符号都是语法产生的。所有语法产生都减少到一个或多个非终结符号和/或终结符号。终端符号是语言关键字。

答案 5 :(得分:0)

我知道这就像是7年的颠簸,但以上所有答案都不正确;尽管罗伯特·库珀(Robert Cooper)说它将破坏语法,这是正确的。

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

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

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

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

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