Подтвердить что ты не робот

"if" блок без фигурных скобок делает последующим "else if" вложенным

AFAIK, если в блоке "if" не указаны фигурные скобки, тогда внутри него рассматривается только 1 оператор. например.

if(..)
  statement_1;
  statement_2;

Независимо от вкладок, в блоке if рассматривается только statement_1.

Следующий код не согласуется с этим:

int main ()
{
  if(false)  // outer - if
    if(false)  // nested - if
      cout << "false false\n";
  else if(true)
    cout << "true\n";
}

Над кодом ничего не печатается. Он должен был напечатать "true".
Похоже, что else if автоматически вставляется внутри внешнего блока if. g++ -Wall выдает предупреждение, но это не вопрос. Как только вы поместите фигурные скобки, все будет хорошо, как ожидалось.

Почему такое поведение? [GCC demo: без брекетов и с фигурными скобками.

4b9b3361

Ответ 1

Поведение на самом деле не отличается от его полностью последовательного: весь внутренний блок if, включая else if, рассматривается как один блок.

Это классическая двусмысленность в разборе, известная как проблема "dangling- else" : существует два допустимых способа разбора этого, когда грамматика написана вниз в нормальном BNF:

Либо конец else является частью внешнего блока, либо внутреннего блока.

Большинство языков разрешают двусмысленность (произвольно), решая, что блоки с жадностью согласовываются с парсером - т.е. else [if] присваивается ближайшему if.

Ответ 2

Поскольку else на самом деле группируется с внутренним if, а не внешним. Он фактически анализируется как

int main ()
{
  if(false)  // outer - if (never gets executed)
  { 
    if(false)  // nested - if
    {
        cout << "false false\n";
    } else if(true) {
        cout << "true\n";
    }
  }
}

Вы можете решить проблему, явно разместив фигурные скобки там, где вы хотите.

Ответ 3

Он ничего не должен печатать. Это эквивалентно этому, так как второе, если /else if - один блок, который принадлежит первому, если:

  if(false) {
    if(false)  // nested - if
      cout << "false false\n";
    else if(true)
      cout << "true\n";
  } 

Ответ 4

Оператор

else всегда присоединяется к ближайшему if. Без ветвей вложенный if сам не формирует значимого утверждения, поэтому парсер продолжается.

Ответ 5

Это вполне естественно из точки синтаксического анализа C.

Парсер, анализируя if-statement, сначала анализирует выражение условия, затем анализирует первый оператор после условия, затем ищет ключевое слово else и, если else представляет, анализирует второй (альтернативный) оператор.

Однако первый оператор также является выражением if, поэтому парсер вызывает "if-parser" рекурсивно (перед тестированием для ключевого слова else)! Этот рекурсивный вызов полностью анализирует внутреннюю инструкцию if-else (в том числе else) и перемещает позицию маркера "за конец" всего фрагмента кода.

Любая попытка реализовать альтернативное поведение должна включать некоторую дополнительную связь между "внешними" и "внутренними" if-parsers: внешний синтаксический анализатор должен информировать "внутреннее", чтобы он не был жадным (т.е. не употреблять инструкцию else). Это добавило бы дополнительную сложность синтаксису языка.