Почему объявление переменной хорошо работает как условие цикла 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;
}
Ответы
Ответ 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", как в первом примере
Проблема решена.