我知道语句后需要分号(我说的是 Java、C++ 和类似语言),但在花括号后不需要分号。为什么这样?
if (a > b)
printf("hello!"); // semicolon is mandatory
if (a > b) {
printf("hello!");
} // semicolon is not required
是什么原因?我的意思是,这背后的理论是什么?
我知道语句后需要分号(我说的是 Java、C++ 和类似语言),但在花括号后不需要分号。为什么这样?
if (a > b)
printf("hello!"); // semicolon is mandatory
if (a > b) {
printf("hello!");
} // semicolon is not required
是什么原因?我的意思是,这背后的理论是什么?
因为花括号用于分组语句,但它们本身不是语句。
因为语言被定义为:
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
解析语句。
撇开哲学推理不谈,在幕后,编译器知道在哪里将每个命令与下一个命令分开是很重要的。括号本身就是分隔符,因此不需要分号。
大多数人认为语句是一个简单的命令,通常带有一个关键字和一些参数,例如“goto x”、“a=y+2”等。必须有一些指示一个语句在哪里结束,另一个在哪里结束开始,就像英语句子需要以句号结尾一样。传统上,大多数语言的语法要求在这样的陈述之后使用分号作为指示。
{ ... } “花括号对”是一个块,这是一种特殊的语句,但不需要分号,因为花括号使边界清晰。
许多语言还允许使用“;” 就其本身而言,表示空语句。你为什么需要一个?出于同样的原因,自然数系统需要“零”而不是“一”,并且集合可以为空。
但这意味着你可以写:
{ ... } ;
并且大多数语言编译器都接受它而不加注释。但是您应该将其视为:
{ ... }
;
通常没有充分的理由来写那个。
实际上,接受{}的语言 (例如,“空括号”)不需要 empty-statement ;,因为它们在语义上是相同的。但是语言设计者似乎停留在传统上。您是否注意到每种“现代”语言似乎都是 C 的糟糕语法副本?
这是一个公平的问题。块是一个语句。渴望统一是很自然的,并想知道为什么所有陈述的结尾都不相同。如果我们确实需要一个;
后块,则没有技术问题。但是我们也很懒,因为}
可以明确地标记语句的结尾,我们不想输入另一个标记。
一个相关的观察:在 C++ 中,你必须以一个结束类声明;
class A
{
...
}; // the semicolon is mandatory!
这惹恼了很多人。分号是必需的,因为语言允许在后面添加一些其他内容,}
因此这}
不是一个可靠的结束标记。
在 Java 中,情况并非如此。结束类声明,}
就是这样。所以;
不需要。
放入分号的效果与
if (a > b) {
printf("hello!");
}printf("Goodbye");
并将printf("Goodbye")
零件留在外面。
如果您在 C# 3+ 中使用对象初始化语法,则分号位于括号后
var foo = new Foo
{
Bar = "Fizzbuzz"
};
在这种情况下,大括号定义了一个语句块。像任何其他块一样。当您要声明和初始化数组时,您必须提供 ; 因为在这种情况下你正在写一个声明。
注意:此答案特定于 C++ 语言,而不是 Java。
我会说语言语法(2003)不需要分号。这就是语言定义语法的方式。
您编写的代码称为复合语句或块,语言规范(2003)在第 6.3/1 节中将复合语句的语法定义为,
为了可以在需要的地方使用多个语句,提供了复合语句(也等效地称为“块”)。
复合语句: {语句序列选择} 语句序列: 陈述 语句序列语句
您在上面显示的语法中看到任何分号吗?不,这就是代码中大括号后不需要分号的原因。
在大括号之后唯一需要分号的地方是在数组初始化之后,因为您可以继续该行,例如
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.
因为 curl 不是用于对语句进行分组的语句。它不需要终结器。
当您使用花括号括起一段代码时,您不需要分号:
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