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

Почему объявление переменной хорошо работает как условие цикла for?

Какое возвращаемое значение/тип объявления типа int i = 5?

Почему не компилируется этот код:

#include <iostream>

void foo(void) {
    std::cout << "Hello";
}

int main()
{
    int i = 0;
    for(foo(); (int i = 5)==5 ; ++i)std::cout << i; 
}

пока это делает

#include <iostream>

void foo(void) {
    std::cout << "Hello";
}

int main()
{
    int i = 0;
    for(foo(); int i = 5; ++i)std::cout << i; 
}
4b9b3361

Ответ 1

Для цикла for условие должно быть выражением или объявлением:

условие - либо

  • выражение, контекстно конвертируемое в bool. Это выражение оценивается перед каждой итерацией, и если оно дает false, цикл завершен.
  • объявление одной переменной с инициализатором скобки или равно. инициализатор оценивается перед каждой итерацией и если значение объявленной переменной преобразуется в значение false, цикл равен вышел.

Первый код не работает, потому что (int i = 5)==5 не является допустимым expression. (Это тоже не объявление). Операнд operator== также должен быть выражением, но int i = 5 является объявлением, а не выражением.

Второй код работает, потому что int i = 5 соответствует второму действительному случаю для условия; объявление одной переменной с равным инициализатором. Значение i будет преобразовано в bool для оценки; который всегда 5, затем приводит к бесконечному циклу.

Ответ 2

Этот код соответствует:

for (foo(); int i = 5 == 5; ++i)

Он проверяет, если 5 == 5 и установите я в этот логический результат (который равен 1) → бесконечный цикл

for(foo(); int i = 5; ++i)

Это просто проверяет значение i после того, как установлено значение 5, поэтому... при преобразовании в bool он всегда true также → бесконечный цикл

Ответ 3

Синтаксис цикла for на языке программирования C следующий:

for ( init; condition; increment ) {
   statement(s);
}

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

Далее выполняется условие. Если это так, то тело цикла выполняется. Если оно ложно, тело цикла не выполняется и поток управления переходит к следующему утверждению сразу после "for", цикл.

После того, как тело цикла 'for' выполняется, поток управляющих переходов вернуться к инструкции инкремента. Это утверждение позволяет вам обновить любые переменные управления контурами.

Учитывая ваш первый программный оператор:

 for(foo(); (int i = 5)==5 ; ++i)std::cout << i;

В приведенном выше описании вы получите следующую ошибку (скомпилированную с использованием GCC):

    error: expected primary-expression before ‘int’
        for(foo(); (int i = 5) == 5; ++i)std::cout << i; 

    error: expected ‘)’ before ‘int’

Первичное выражение в C может быть любым из множества вещей:

a name (of a variable or a function)
a typename
an operator
a keyword like if or while
the list goes on and on ...

Эта ошибка объясняется тем, что оператор (int i = 5) == 5 не является допустимым выражением, а компилятор пытается интерпретировать каким-то другим способом. Тем не менее, вторая программа работает как объявление int i = 5, которая может использоваться как допустимое условие для цикла condition для цикла, поскольку такое объявление оценивает значение initializer, которое 5 в вашей второй программе. Тем не менее, вторая программа будет бесконечным циклом и будет печатать 5 на терминале. Однако, если значение инициализатора было 0, тогда условие evalautes на false при первой проверке и тело цикла for не выполняться ни разу.

Ответ 4

Хотя в соответствии с синтаксисом for цикл должен начинаться оператор инициализации, а затем проверка и затем обновление, так как ваш проверочный оператор является инициализацией во втором примере, я инициализируется как 5 как часть проверки и для цикла продолжается.

Использование вызова foo() при инициализации не имеет никакого отношения к циклу for, поскольку тип возврата является недействительным, , если вы помещаете 0 вместо foo(), вы получите тот же результат

Теперь рассмотрим первый пример, ваш проверочный оператор является инициализацией, как и второй пример, и он будет работать, если у вас не было этих скобок. Поскольку декларация не возвращает никакого значения, (int я = 5) не возвращает никакого значения и поэтому не может сравниться с 5 в "== 5".

Однако, если вы попробуете "для (foo(); int я = 5 == 5; ++ i)..." , оператор проверки компилируется так же, как int я = (5 == 5). Поскольку значение 5 == 5 истинно, оно возвращает значение 1, которое затем инициализируется как значение i. Таким образом, выход 11111......

TL; DR: Поскольку декларация не возвращает никакого значения, (int я = 5) не возвращает никакого значения и, следовательно, не может сравниться с 5 в "== 5", как в первом примере

Проблема решена.