2016-10-12 8 views
20

Что такое возвращаемое значение/тип декларации, например int i = 5?Почему объявление переменной хорошо работает как условие цикла for?

Почему не компилировать этот код:

#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

Поскольку 'int i = 5' не является допустимым выражением? И вам нужно правильное выражение в круглых скобках. –

+0

Даже если ваша вторая программа компилируется, вы будете поражены бесконечным циклом. Он будет печатать «5» на терминале. – abhiarora

+1

Что еще более интересно, так это то, что если вы инициализируете i до 0, он возвращает false. –

ответ

25

Петля forтребует условие быть либо выражение или заявление:

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

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

1-код не работает, потому что (int i = 5)==5 не является допустимым expression вообще. (Это тоже не декларация.) Предполагается, что также операнд operator==, но int i = 5 - это объявление, а не выражение.

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

+1

Я понятия не имел, что вы можете объявить переменную в состоянии цикла for! –

2

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

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

Проверяется 5 == 5 и я ставил на это boolean result (which is 1) -> бесконечный цикл

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

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

+0

'i! = NULL' немного странно, вы могли бы означать' i! = False'? – songyuanyao

+0

Поскольку NULL == 0, я не вижу ничего странного здесь, я не логический. В любом случае, ответ выше лучше, лучше;) – Treycos

+0

Точнее, значение 'i' будет преобразовано в' bool' , затем используется для суждения; 'NULL' или' 0' не задействован в этом процессе. Во всяком случае, результат тот же. – songyuanyao

0

Синтаксис для цикла в языке программирования 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 не будет выполнено даже один раз.

+0

Цитата, которую вы указали, ничего не говорит о объявлении переменных в части «условие», она упоминает объявления только в части «init» (что намекает на то, что объявления не разрешены в других частях). Кроме того, могут быть различия между C и C++. – ilkkachu

+0

Я упомянул ниже: «Однако вторая программа работает как объявление int i = 5, как допустимое условие для проверки условий в цикле, поскольку такое объявление оценивает значение инициализатора, которое равно 5 во второй программе». – abhiarora

-3

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

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

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

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

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

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

+0

_ "Так как декларация не возвращает никакого значения, (int i = 5) ... не может сравниться ..." _ - Ну, но вопрос, похоже, заключается в том, почему это _can_, однако, неявно сравнивается для правды во втором примере. Разве в вашем ответе нет противоречия? Я не вижу, как «int i = 5 == 5» приходит к нему, поскольку это просто странный способ сказать «int i = 1», что очень похоже на фрагмент в вопросе. – ilkkachu

+0

Высказывание int i = 1 является объявлением в проверочном заявлении, компилятору все равно, пока оператор исполняется. Поэтому вместо проверки, когда он должен проверяться, он сохраняет инициализацию i до 1. Попробуйте выполнить инициализацию в условии if. Что-то вроде if (i = 1) {...} в этом случае, i инициализируется 1, и оператор if выполняется. – Zac

 Смежные вопросы

  • Нет связанных вопросов^_^