I++ и ++i в цикле for()

#include <iostream>
using namespace std;

int main()
{
    int i;
    for (i = 0; i < 5; ++i)
    {
        std::cout << i << endl;
        // Почему здесь i={0-4}, а не i={1-5}?
        // ведь ++i
    }

    // А здесь всё в порядке.
    int x = 5;
    int y;

    y = ++x; // y = 6, x = 6
    std::cout << "y = " << y << ", x = "<< x <<"\n"<< endl;

    y = --x; // y = 5, x = 5
    std::cout << "y = " << y << ", x = "<< x <<"\n"<< endl;

    y = x++; // y = 5, x = 6
    std::cout << "y = " << y << ", x = "<< x <<"\n"<< endl;

    return 0;
}

Вот что получились:

$ ./test 
0
1
2
3
4
y = 6, x = 6

y = 5, x = 5

y = 5, x = 6

Почему здесь i={0-4}, а не i={1-5}? ведь ++i

Для цикла for нет разницы между префиксным и постфиксным инкрементом (декрементом).

Эти два цикла практически эквивалентны:

int i;
// (1)
for (i = 0; i < 5; ++i) {
    // тело цикла
}

// (2)
i = 0;
while (i < 5) {
    // тело цикла
    ++i;  // оператор выполняется строго ПОСЛЕ тела цикла
}

Разобрался, но логики пока не понял. Без цикла работает логично а в цикле по определению после тела.

for( AAAA ; BBBB ; ++i ) {
    ZZZZ;
}

эквивалентно

AAAA;
while ( BBBB ) {
    ZZZZ;
    ++i;
}

Если стоит постфиксный инкремент (i++), цикл выполняется в следующем порядке:

Инициализация счётчика
Проверка счётчика
Выполнение тела цикла
Инкремент счётчика
Проверка счётчика

А если префиксный инкремент (++i), в следующем:

Инициализация счётчика
Проверка счётчика
Инкремент счётчика
Выполнение тела цикла
Проверка счётчика

В первом случае сперва выполняется тело цикла, а потом изменяется значение счётчика, во втором — сперва изменяется значение, а потом выполняется тело цикла. Но в обоих случаях, к следующей проверке, значение счётчика уже изменится. Поэтому на результат работы цикла это не влияет.

Slonopotam, не сбивай человека с толка. В операторе for ВСЕГДА сначала выполняется тело цикла, а потом вычисляется выражение, стоящее на третьем месте в операторе (это не обязательно инкремент).

Example:

#include <iostream>

using namespace std;

int main() {
    int i;

    for (i = 0; i < 5; i++)
        cout << i << ' ';
    cout << endl;

    for (i = 0; i < 5; ++i)
        cout << i << ' ';
    cout << endl;

    return 0;
}

Каков должен быть вывод на экран по твоей теории?

Torovich, твою схему я бы даже обобщил:

for( AAAA ; BBBB ; CCCC ) {
    ZZZZ;
}

эквивалентно (без учёта оператора continue)

AAAA;
while ( BBBB ) {
    ZZZZ;
    CCCC;
}

По моей теории вывод на экран будет одинаковый. О чём я и написал.

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

Человек спросил про логику, я ему логику и объяснил. Пусть она и не верная, но однозначно логичная и не противоречит результату работы инкремента в цикле.
До этой логики я дошёл сам, когда задавался тем же вопросом, что и Torovich. Сейчас заглянул в msdn. И признаю — Да, я ошибался — «At the end of each iteration of statement.»

Слава Богу, что ты признал свою ошибку. Но я тебя таки постараюсь добить ;-) Не из садизма, а для прояснения тонкого момента.

По моей теории вывод на экран будет одинаковый. О чём я и написал.

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

По твоей теории выдача должна быть разной. Здесь вопрос не о том, когда циклы завершатся (а завершатся они в обоих случаях после пятой итерации), а о том, какое значение будет иметь счётчик при исполнении тела цикла. Если бы префиксный инкремент происходил до выполнения тела цикла, то выдача была бы 1 2 3 4 5, а не 0 1 2 3 4.

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.