Сделать цикл пропуская четное число - PullRequest
2 голосов
/ 24 мая 2019

I представляет глобальную переменную, т.е. имя I представляет одну и ту же переменную внутри и снаружи функции. Факт сначала вызывается, когда I = 1, что является первым записанным значением. Это значение передан фиктивному аргументу функции N. То же самое I теперь получает начальное значение 2 в цикле DO внутри Fact, но, поскольку оно больше N, цикл DO не выполняется, поэтому у меня все еще есть значение 2 когда Факт возвращается для печати в основной программе. Тем не менее, я теперь увеличен до 3 в Цикл DO в основной программе, то есть значение, которое он имеет, когда происходит второй вызов Fact.

PROGRAM Factorial 
IMPLICIT NONE 
INTEGER I

DO I = 1, 10 
PRINT*, I, Fact(I) 
END DO

 CONTAINS 
 FUNCTION Fact( N ) 
INTEGER Fact, N, Temp 
Temp = 1 
DO I = 2, N 
  Temp = I * Temp 
END DO 
Fact = Temp 
END FUNCTION 
 END

и как только он завершится, I переходит от 2 к N, где теперь N = 3. Теперь функция должна возвращать I = 3 в основную программу, так что следующим я должен быть 4 в цикле Do основной программы, но при компиляции и запуске ..это только показывает коэффициент для 3,5,7 и 9 ..... Мой вопрос, почему он пропускает 4 или 6 или 8.

1 Ответ

1 голос
/ 24 мая 2019

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


Мало того, вы используете псевдоним для глобального I, используя его в качестве I в качестве N одновременно в функции. Компилятор, вероятно, может выполнять различные оптимизации, предполагая, что они различны, когда фактически ссылаются на одну и ту же переменную. Поэтому программа снова незаконна и непредсказуема.

Рассмотрите этот пример и попробуйте скомпилировать его с разными уровнями оптимизации. Вы получите разные ответы:

i = 1
call s(i)

contains

  subroutine s(j)
    do k = 1, 10
      j = i + j
    end do
    print *, j
  end
end

Попробуйте онлайн!

Эту конкретную проблему, вероятно, можно решить, объявив i или фиктивный аргумент target.

...