Почему точка с запятой не требуется после скрученной скобки?

Я знаю, что точка с запятой необходима после оператора (я говорю о Java, C++ и подобных языках), но не обязательна после скрученной скобки. Почему так?

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

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

Какова причина? Я имею в виду, какая теория стоит за этим?

12 ответов

Решение

Потому что фигурные скобки используются для группировки операторов, но сами по себе они не являются.

Потому что язык определяется как:

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" и т. Д. Должно быть какое-то указание того, где заканчивается один оператор, а другой - начинается, так же, как английские предложения должны заканчиваться точкой. Традиционно грамматики большинства языков требуют точек с запятой после такого утверждения в качестве такого указания.

{ ... } "пара фигурных скобок" - это блок, который является особым видом оператора, но точка с запятой не нужна, потому что фигурные скобки проясняют границы.

Многие языки также позволяют ";" само по себе, чтобы представить пустое утверждение. Зачем вам нужен? По той же причине система натуральных чисел требует "ноль" вместо "один", и множества могут быть пустыми.

Но это означает, что вы можете написать:

{ ... } ;

и большинство компиляторов языка принимает это без замечаний. Но вы должны думать об этом как:

{  ... }
;

и вообще нет веской причины писать это.

На практике, языки, которые принимают {} (например, "пустые скобки"), не нуждаются в пустом выражении ; потому что они семантически идентичны. Но дизайнеры языка, похоже, застряли на традициях; Вы заметили, что каждый "современный" язык кажется плохой синтаксической копией C?

Это справедливый вопрос. Блок это утверждение. Естественно стремиться к единообразию и удивляться, почему все утверждения не заканчиваются одинаково. Нет технической проблемы, если нам требуется ; после блока. Но мы также ленивы, так как } можем однозначно отметить конец оператора, нам не нужно вводить другой маркер.

Связанное наблюдение: в C++ вы должны завершить объявление класса ;

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

Это раздражает чертовски много людей. Точка с запятой обязательна, потому что язык позволяет некоторые другие вещи после } Итак } не является надежным маркером конца.

В Java это не так. } заканчивает объявление класса и все. Так ; не нужен

Если вы используете синтаксис инициализации объекта в C# 3+, после скобки следует точка с запятой

var foo = new Foo
  {
    Bar = "Fizzbuzz"
  };

Единственное место, где вам понадобится точка с запятой после закрывающей фигурной скобки, это после инициализации массива, так как вы можете продолжить строку, например

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.

В этом случае фигурные скобки определяют блок операторов. Как и любой другой блок. пока вы собираетесь объявить и инициализировать массив, вы должны предоставить; потому что в этом случае вы пишете заявление.

Ввод точки с запятой такой же, как

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

и оставив printf("Goodbye") расстаться.

Примечание: этот ответ относится только к языку C++, а не к Java.

Я бы сказал, что точка с запятой не требуется для грамматики языка (2003). Вот как язык определяет грамматику.

Код, который вы написали, называется составным оператором или блоком, а языковая спецификация (2003) определяет грамматику составного оператора в разделе §6.3/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

Поскольку curly не является оператором, он используется для группировки операторов. Для этого не нужен терминатор.

Другие вопросы по тегам