为什么第二个if子句甚至执行?

时间:2013-04-22 17:37:39

标签: fortran

我的程序中有一个do while循环,有条件继续不断地给我一个错误,我无法弄清楚原因。它看起来像这样:

do while (ii .le. nri .and. ed(ii) .le. e1)
    ! do some stuff...
    ii = ii + 1
end do

其中iinri是标量整数,e1是标量实数,ed是一个长度为nri的真实数组。我希望在最后一次运行后发生的事情是,因为ii.le.nri返回.false.,所以第二个条件从未经过测试,而且我没有得到任何一个一个一个的问题。我已经通过调试器验证ii.le.nri确实 返回.false. - 但程序崩溃了。

为了验证我的假设只测试了一个条件,我甚至编写了一个小的测试程序,我使用相同的编译器选项编译:

 program iftest
     implicit none

     if (returns_false() .and. returns_true()) then
         print *, "in if block"
     end if
 contains
     function returns_true()
         implicit none
         logical returns_true
         print *, "in returns true"
         returns_true = .true.
     end function

     function returns_false()
         implicit none
         logical returns_false
         print *, "in returns false"
         returns_false = .false
     end function
 end program

正如我所料,运行此程序输出仅

 $ ./iftest
 in returns false

并退出。第二次测试永远不会运行。

为什么这不适用于我的do while条款?

2 个答案:

答案 0 :(得分:7)

与某些语言相比,Fortran不保证复合逻辑表达式的任何特定评估顺序。对于您的代码,最后围绕while循环,ii的值设置为nri+1。编译器生成测试ed(nri+1)<=e1的代码从而引用ed范围之外的元素是合法的。这可能是程序崩溃的原因。

您的期望与该语言的Fortran标准处方相反。

如果您还没有这样做,请尝试重新编译代码,并打开数组边界检查,看看会发生什么。

至于为什么你的测试没有冒出这个问题,我怀疑你的所有测试都表明你的编译器为不同的条件种类生成了不同的执行顺序,并且你并没有真正比较像样。

答案 1 :(得分:4)

扩展答案High Performance Mark,这是重写循环的一种方法:

ii_loop: do

  if (ii .gt. nri) exit ii_loop
  if (ed(ii) .gt. e1) exit ii_loop

  ! do some stuff

  ii = ii + 1

end do ii_loop