Вопрос про цикл for

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

xchgeaxeax
постоялец
Сообщения: 201
Зарегистрирован: 11.05.2023 02:51:40

Сообщение xchgeaxeax »

Seenkao писал(а):Если хочешь то можешь привести пример, когда значение не определено для значения счётчика по выходу из цикла.
Я говорил про то, что в разных реализациях компиляторов паскаля цикл for может организовываться по разному и счетчик после цикла не имеет точного значения. Т.е. какой-то компилятор может выполнять проверку на достижение значения последнего элемента цикла, а какой-то на выход за рамки указанного диапазона значений. Или у одного компилятора цикл for использует прединкременты, а в большинстве постинкременты. Как на C можно писать for (i = 0; i < 9; ++i) или for (i = 0; i <= 8; ++i) или for (i = 0; i < 9; i++) или for (i = 0; i <= 8; i++) или for (i = 0; ++i < 9; ) или for (i = 0; ++i <= 8; ) или for (i = 0; i++ < 8; ) или for (i = 0; i++ <= 7; )
Поэтому для переносимости кода надо воспринимать значение счетчика цикла for как неопределенное.
Seenkao писал(а):по сути там не должно сохраняться i = 5, по простой причине, что данная переменная задействована. Какова правильная реализация в Си, не знаю. В Паскале не сохранится.
Этим и отличается C от Паскаля. В паскале все переменные предопределяются перед блоком их действия, а в С все переменные объявляются в блоке их действия или предыдущих. Т.е.

Код: Выделить всё

int i = 5; // это одна переменная
for (int i = 0...) // Это другая переменная объявленная в блоке for, но с тем же именем
Вот так будет нагляднее

Код: Выделить всё

#include <iostream>

int main(int argc, char *argv[]) {
    int i = 5;
    for (int i = 0; i <= 8; ++i) std::cout << &i << " = " << i << " ";
    std::cout << std::endl << &i << " = " << i << std::endl;
    for (int i = 0; i <= 8; ++i) {
      if (i == 8) break;
      std::cout << &i << " = " << i << " ";
    }
    std::cout << std::endl << &i << " = " << i << std::endl;
    return 0;
}
0x7fffbb42c3e4 = 0 ... = 1 ... = 2 ... = 3 ... = 4 ... = 5 ... = 6 ... = 7 ... = 8
0x7fffbb42c3e0 = 5
0x7fffbb42c3e4 = 0 ... = 1 ... = 2 ... = 3 ... = 4 ... = 5 ... = 6 ... = 7
0x7fffbb42c3e0 = 5
svk12
постоялец
Сообщения: 411
Зарегистрирован: 09.06.2008 18:42:47

Сообщение svk12 »

ZWolol писал(а):Вопрос стоял в том: почему результат i нельзя использовать.
Условие продолжения цикла for проверяется до выполнения тела цикла,
поэтому на последнем шаге переменная цикла достигнет предельного значения, случился ли там break или нет.
Seenkao
энтузиаст
Сообщения: 569
Зарегистрирован: 01.04.2020 02:37:12
Контактная информация:

Сообщение Seenkao »

xchgeaxeax писал(а):Вот так будет нагляднее
подобные действия ЯП ломают правильное понимание работы кода. Из-за этого и не понимание топикстартера, как работает код.

Вообще мне многим из подобных действий Си (или подобных ему ЯП) и не нравится. Каждый раз когда заходишь в функцию, там объявляется переменная (должна объявляться), но в каких-то реализациях вызывая очередной раз функцию, оказывается, что переменная уже имеет конкретное значение и работает именно от этого значения, а не от начального, как ожидаешь.
ZWolol
новенький
Сообщения: 21
Зарегистрирован: 06.01.2023 05:49:21

Сообщение ZWolol »

В общем я понял, что на результат влияют много параметров: версия компилятора и то как звезды сошлись.
У меня на Borland C 3.2, Borland C++ Builder 6.0 и Microsoft C++ 5.0 звезды не влияли.
Ну что ж, учтем...
Аватара пользователя
Sharfik
энтузиаст
Сообщения: 836
Зарегистрирован: 20.07.2013 01:04:30

Сообщение Sharfik »

xchgeaxeax писал(а):Я говорил про то, что в разных реализациях компиляторов паскаля цикл for может организовываться по разному и счетчик после цикла не имеет точного значения. Т.е. какой-то компилятор может выполнять проверку на достижение значения последнего
В какой версии и при каких настройках FPC переменную i не сохранит с значением на котором у цикла был break?
xchgeaxeax
постоялец
Сообщения: 201
Зарегистрирован: 11.05.2023 02:51:40

Сообщение xchgeaxeax »

Sharfik писал(а):В какой версии и при каких настройках FPC переменную i не сохранит с значением на котором у цикла был break?
Если ограничиваться только FPC, тогда, возможно, что в любой версии значение будет корректным, а вот за другие компиляторы - не буду даже пытаться утверждать.
ZWolol
новенький
Сообщения: 21
Зарегистрирован: 06.01.2023 05:49:21

Сообщение ZWolol »

@Sharfik
>В какой версии и при каких настройках FPC переменную i не сохранит с значением на котором у цикла был break?
Проблем с номером i для break нет, но без break i равна последнему значению.
и нет возможности определить был ли break на последней строке или нет.

Lazarus
Версия: 2.2.4
Дата: 2022-09-24
Версия FPC: 3.2.2
Ревизия: lazarus_2_2_4
x86_64-win64-win32/win64

Настройки не менял, использовал все по умолчанию.
RRYTY
постоялец
Сообщения: 253
Зарегистрирован: 25.12.2021 09:00:32

Сообщение RRYTY »

Так и должно быть. Для определения достижения условия в цикле используйте отдельную переменную типа boolean.
Аватара пользователя
Снег Север
долгожитель
Сообщения: 3067
Зарегистрирован: 27.11.2007 15:14:47
Контактная информация:

Сообщение Снег Север »

RRYTY писал(а):Для определения достижения условия в цикле используйте отдельную переменную типа boolean.
Но почему обязательно boolean? Любую переменную, в зависимости от цели такого определения - например того же типа, что элементы просматриваемого массива и присваивать значение найденного элемента.
Mikhail
энтузиаст
Сообщения: 565
Зарегистрирован: 24.10.2013 16:06:47

Сообщение Mikhail »

О чем спор? Вот выдержка из документации.
The value of the loop variable is undefined after a loop has completed or if a loop is not executed at all. However, if the loop was terminated prematurely with an exception or a break or goto statement, the loop variable retains the value it had when the loop was exited.
Ну и использование цикла for для такой задачи не лучшая идея.
RRYTY
постоялец
Сообщения: 253
Зарегистрирован: 25.12.2021 09:00:32

Сообщение RRYTY »

Снег Север писал(а):Но почему обязательно boolean?
Потому что break либо был, либо нет. Условие проверено в цикле.
Аватара пользователя
Sharfik
энтузиаст
Сообщения: 836
Зарегистрирован: 20.07.2013 01:04:30

Сообщение Sharfik »

RRYTY писал(а):
Снег Север писал(а):Но почему обязательно boolean?
Потому что break либо был, либо нет. Условие проверено в цикле.
В случае вопроса темы Boolean прекрасно заменяется на Integer и выполняет ту же функцию и при этом отображает был найден или нет объект. Два параметра одной переменной. iResult>-1 значит что то нашли.
DedFrend
постоялец
Сообщения: 157
Зарегистрирован: 25.11.2018 11:21:50

Сообщение DedFrend »

По мне вопрос не в том - сработает или нет. Вопрос - а на фига?
Вам не жалко человека, который, возможно, будет такое читать? Зачем усложнять ему жизнь, когда можно do while использовать?
xchgeaxeax
постоялец
Сообщения: 201
Зарегистрирован: 11.05.2023 02:51:40

Сообщение xchgeaxeax »

DedFrend писал(а):Вам не жалко человека, который, возможно, будет такое читать? Зачем усложнять ему жизнь, когда можно do while использовать?
do while? Может repeat <operators> until <false_condition>. do {} while (<true_condition>) это из С.
ZWolol
новенький
Сообщения: 21
Зарегистрирован: 06.01.2023 05:49:21

Сообщение ZWolol »

Меня интересовало лишь: почему for на паскале работает не как на других языках?
Но если в описании сказано, что так и должно быть, то у меня вопросов больше нет.

Наверняка можно это исправить, но основное правило программиста:
если заметил, что что-то работает не так, то лучше указать в описании на эту "особенность" программы.
иначе, исправляя это получишь другие косяки... :)
Ответить