簡體   English   中英

為什么函數中的花括號在 C 風格的語言中不是可選的?

[英]Why are curly braces in functions not optional in C-style languages?

語言設計者選擇在以下場景中使用大括號可選:

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

為什么在函數中不允許相同,像這樣?

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

我敢肯定這會搞亂語法。 例如,這個空函數定義之間沒有區別......

void empty()
{
    ;
}

...還有這個函數聲明:

void empty();

我不確定他們確實“選擇”了這個。 相反,省略花括號 for if、while、for 等的能力是它們指定語法的方式的自然結果。 語法禁止它用於函數可能是因為舊式的函數聲明。

沒有與函數定義相關的固定關鍵字。 對於if / else / for / while / switch有一個這樣的關鍵字標志着邏輯控制結構的開始。

盡管上下文允許我們人類辨別int some_name (some_expression) some_other_expressions; 是一個函數 - 在編程實踐中(盡管明確可行)需要大量回溯以確保標記流中前面的 3-4-6 個符號沒有將其從函數聲明更改為其他內容。

一個編程語言解析器可以根據它的解析方法進行分類,要么獲取標記列表中的當前標記並檢查下一個標記是否確認“這是一個 if”或“這是一個函數”,或者它需要一個最大的查找-提前標記(2-3-6?)並確認“這可能是一個函數”,“現在我看到第 5 個標記,這肯定是一個函數”,或者它使用回溯和可變前瞻方法,走得更遠在令牌列表中根據需要確保我們正在研究的構造不是別的東西。

如果我要推測,我會說這是因為一個函數通常包含多個語句,而 if 或 while 語句通常只包含一個語句。 此外,事實證明它是有遠見的,因為在 C++ 中允許省略 {} 會導致成員函數中的歧義。 例如:

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

花括號不是“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 所有非終結符都是語法產生式。 所有語法產生式都簡化為一個或多個非終結符和/或終結符。 終結符是語言關鍵字。

我知道這就像 7 年的顛簸,但以上所有答案都不正確; 盡管 Robert Cooper 說這會破壞語法是對的。

真正的問題與 C 的原始版本的外觀有關:

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

默認情況下,C 中的所有內容都是 int,因此可以省略大部分類型注釋。 現代 C 與此完全向后兼容,因為人們不想丟棄或更新一堆現有代碼。

請注意,函數參數列表之后的類型注釋看起來與普通變量聲明完全一樣。 這是故意這樣做的,可能是為了簡化原始語法,但這意味着嘗試定義一個沒有大括號的函數,就像你的例子那樣是完全不明確的。

基本上,它無法工作,因為解析器無法區分聲明語句和類型注釋之間的區別。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM