13

我知道语句后需要分号(我说的是 Java、C++ 和类似语言),但在花括号后不需要分号。为什么这样?

if (a > b) 
  printf("hello!"); // semicolon is mandatory

if (a > b) {
  printf("hello!");
} // semicolon is not required

是什么原因?我的意思是,这背后的理论是什么?

4

12 回答 12

8

因为花括号用于分组语句,但它们本身不是语句。

于 2011-04-06T05:31:01.260 回答
8

因为语言被定义为:

statement:
    labeled-statement
    expression-statement
    compound-statement
    selection-statement
    iteration-statement
    jump-statement
    declaration-statement
    try-block

labeled-statement:
    identifier : statement
    case constant-expression : statement
    default : statement

expression-statement:
    expressionopt ; 

compound-statement:
    { statement-seqopt } 

statement-seq:
    statement
    statement-seq statement

selection-statement:
    if ( condition ) statement
    if ( condition ) statement else statement
    switch ( condition ) statement

condition:
    expression
    type-specifier-seq declarator = assignment-expression

iteration-statement:
    while ( condition ) statement
    do statement while ( expression ) ; 
    for ( for-init-statement conditionopt ; expressionopt ) statement

for-init-statement:
    expression-statement
    simple-declaration

jump-statement:
    break ;
    continue ;
    return expressionopt ; 
    goto identifier ; 

declaration-statement:
    block-declaration 

所有正常的控制语句都是相互递归构建的。真正的工作是由expression-statement. 如果您注意到expression-statement总是由;. 其他要注意的语句是jump-statement.

但主要原因是在 {} 块之后不需要它们来允许easy解析语句。

于 2011-04-06T05:45:38.767 回答
5

撇开哲学推理不谈,在幕后,编译器知道在哪里将每个命令与下一个命令分开是很重要的。括号本身就是分隔符,因此不需要分号。

于 2011-04-06T05:33:56.893 回答
3

大多数人认为语句是一个简单的命令,通常带有一个关键字和一些参数,例如“goto x”、“a=y+2”等。必须有一些指示一个语句在哪里结束,另一个在哪里结束开始,就像英语句子需要以句号结尾一样。传统上,大多数语言的语法要求在这样的陈述之后使用分号作为指示。

{ ... } “花括号对”是一个,这是一种特殊的语句,但不需要分号,因为花括号使边界清晰。

许多语言允许使用“;” 就其本身而言,表示空语句。你为什么需要一个?出于同样的原因,自然数系统需要“零”而不是“一”,并且集合可以为空。

但这意味着你可以写:

{ ... } ;

并且大多数语言编译器都接受它而不加注释。但是您应该将其视为:

{  ... }
;

通常没有充分的理由来写那个。

实际上,接受{}的语言 (例如,“空括号”)不需要 empty-statement ,因为它们在语义上是相同的。但是语言设计者似乎停留在传统上。您是否注意到每种“现代”语言似乎都是 C 的糟糕语法副本?

于 2011-04-06T05:30:59.090 回答
1

这是一个公平的问题。块一个语句。渴望统一是很自然的,并想知道为什么所有陈述的结尾都不相同。如果我们确实需要一个;后块,则没有技术问题。但是我们也很懒,因为}可以明确地标记语句的结尾,我们不想输入另一个标记。

一个相关的观察:在 C++ 中,你必须以一个结束类声明;

class A
{
    ...
}; // the semicolon is mandatory!

这惹恼了很多人。分号是必需的,因为语言允许在后面添加一些其他内容,}因此这}不是一个可靠的结束标记。

在 Java 中,情况并非如此。结束类声明,}就是这样。所以;不需要。

于 2011-04-06T08:17:35.993 回答
0

放入分号的效果与

if (a > b) {
 printf("hello!");
}printf("Goodbye");

并将printf("Goodbye")零件留在外面。

于 2011-04-06T05:33:32.730 回答
0

如果您在 C# 3+ 中使用对象初始化语法,则分号位于括号后

var foo = new Foo
  {
    Bar = "Fizzbuzz"
  };
于 2011-04-06T05:35:02.950 回答
0

在这种情况下,大括号定义了一个语句块。像任何其他块一样。当您要声明和初始化数组时,您必须提供 ; 因为在这种情况下你正在写一个声明。

于 2011-04-06T05:35:36.110 回答
0

注意:此答案特定于 C++ 语言,而不是 Java。

我会说语言语法(2003)不需要分号。这就是语言定义语法的方式。

您编写的代码称为复合语句或块,语言规范(2003)在第 6.3/1 节中将复合语句的语法定义为,

为了可以在需要的地方使用多个语句,提供了复合语句(也等效地称为“块”)。

复合语句:  
             {语句序列选择}

语句序列:  
            陈述
            语句序列语句

您在上面显示的语法中看到任何分号吗?不,这就是代码中大括号后不需要分号的原因。

于 2011-04-06T05:47:03.137 回答
0

在大括号之后唯一需要分号的地方是在数组初始化之后,因为您可以继续该行,例如

int[] i= { 1,2,3}, j= {1};

分号是必需的,因为这里的 '}' 不会告诉编译器行尾在哪里。

相似地

Runnable r = new Runnable() {
   public void run() {
   }
}, r2 = new Runnable() {
   public void run() {
   }
}; // required as you could define another Runnable or an array of Runnable.
于 2011-04-06T06:25:14.163 回答
-1

因为 curl 不是用于对语句进行分组的语句。它不需要终结器。

于 2011-04-06T05:32:16.150 回答
-1

当您使用花括号括起一段代码时,您不需要分号:

namespace Some
{
  void fun(int i)
  { 
    while(i != 0)
    {
      cout<<"i = "<<i<<endl;
      i --;
    }  // semicolon not needed
  }  // semicolon not needed
} // semicolon not needed

在其他情况下,您需要分号(如初始化、声明等):

struct A {
// ... declare members
}; // declaration; put semicolon
int a[] = {0, 1, 2};  // initialization; put semicolon
于 2011-04-06T06:05:49.597 回答