Ответ 1
Поскольку фигурные скобки используются для группировки операторов, но они не являются самими утверждениями.
Я знаю, что после оператора требуется точка с запятой (я говорю о Java, С++ и подобных языках), но не требуется после скрученной скобки. Почему так?
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" и т.д. Должно быть какое-то указание на то, заканчивается, а другой начинается, как и английские фразы, нужно заканчивать период. Традиционно грамматикам большинства языков требуется точка с запятой после такого утверждения как таковое указание.
A {...} "фигурная скобка" - это блок, который является особым видом выражения, но точка с запятой не нужна, потому что фигурные скобки делают границы четкими.
Многие языки также позволяют ";" само по себе, чтобы представить пустое утверждение. Зачем вам это нужно? По той же причине система натуральных чисел требует "нуля" вместо "одного", а множества могут быть пустыми.
Но это означает, что вы можете написать:
{ ... } ;
и большинство компиляторов langauge принимают его без замечаний. Но вы должны думать об этом как:
{ ... }
;
и, как правило, нет оснований писать это.
Как правило, для языков, принимающих {} (например, "пустые скобки" ), не требуется пустой оператор ;, потому что они семантически идентичны, Но языковые дизайнеры, похоже, придерживаются традиции; вы заметили, как каждый "современный" язык кажется плохой синтаксической копией C?
Это справедливый вопрос. Блок - это оператор. Естественно желать единообразия и удивляться, почему все утверждения не прекращаются одинаково. Технической проблемы нет, если нам понадобится ;
после блока. Но мы также ленивы, так как }
может однозначно пометить конец утверждения, мы не хотим вводить другой маркер.
Связанное наблюдение: в С++ вы должны объявить объявление класса с помощью ;
class A
{
...
}; // the semicolon is mandatory!
Это раздражает многих людей. Точка с запятой требуется, потому что язык разрешает некоторые другие вещи после }
, поэтому }
не является надежным маркером конца.
В Java это не так. }
завершает объявление класса, и это все. Поэтому ;
не требуется.
Ввод точки с запятой в тот же эффект, что и
if (a > b) {
printf("hello!");
}printf("Goodbye");
и оставить часть printf("Goodbye")
.
Если вы используете синтаксис инициализации объекта в С# 3+, точка с запятой приходит после скобки
var foo = new Foo
{
Bar = "Fizzbuzz"
};
В этом случае фигурные скобки определяют блок операторов. Как и любой другой блок. пока вы собираетесь объявить и инициализировать массив, который вы должны предоставить; потому что в этом случае вы пишете выражение.
Примечание: этот ответ специфичен для языка С++, а не для Java.
Я бы сказал, что точка с запятой не требуется грамматикой языка (2003). Вот как язык определяет грамматику.
Код, который вы написали, называется Compound statement или block, а спецификация языка (2003) определяет грамматику составного оператора в разделе §6.3/1 as,
Чтобы можно было использовать несколько утверждений где ожидается, соединение (также и, что то же самое, называемый "блок" ).
compound-statement: { statement-seqopt } statement-seq: statement statement-seq statement
Вы видите какую-либо полуточку в приведенной выше грамматике? Нет. То, почему полуколонна не требуется после фигурного скобки в вашем коде.
Единственное место, где вам понадобится точка с запятой после закрывающей фигурной скобки, - это после инициализации массива, поскольку вы можете продолжить линию, например.
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.
Потому что curly - это не оператор, который используется для группировки операторов. Он не нуждается в терминаторе.
Когда вы используете фигурные скобки, чтобы заключить блок кода, вам не нужна точка с запятой:
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