在英特尔论坛上将此报告为编译器错误之前,我想知道以下是否符合标准。我的问题是:逻辑运算的顺序是否总是在Fortran中修复?
! main.f90
interface
subroutine f(x)
logical, intent(in), optional :: x
end subroutine f
end interface
call f(.false.)
call f(.true.)
call f()
end program
! f.f90
subroutine f(x)
logical, intent(in), optional :: x
print*, present(x) .and. x
end subroutine f
gfortran main.f90 f.f90 && ./a.out
打印
F
T
F
ifort main.f90 f.f90 && ./a.out
打印
F
T
forrtl: severe (174): SIGSEGV, segmentation fault occurred
Image PC Routine Line Source
a.out 0000000000476D75 Unknown Unknown Unknown
a.out 0000000000474997 Unknown Unknown Unknown
a.out 0000000000444264 Unknown Unknown Unknown
a.out 0000000000444076 Unknown Unknown Unknown
a.out 0000000000425176 Unknown Unknown Unknown
a.out 00000000004027A0 Unknown Unknown Unknown
libpthread.so.0 00007F3560702E80 Unknown Unknown Unknown
a.out 0000000000402633 Unknown Unknown Unknown
a.out 000000000040260F Unknown Unknown Unknown
a.out 00000000004025AE Unknown Unknown Unknown
libc.so.6 00007F3560371710 Unknown Unknown Unknown
a.out 00000000004024A9 Unknown Unknown Unknown
我正在使用GCC 5.3.0和Ifort 16.0.2。
答案 0 :(得分:9)
不,Fortran标准不保证评估逻辑表达式的顺序。像数学表达式一样,编译器可以自由地将它们重新排序为顺序,这些顺序在“真实逻辑”的完美世界中是等价的。 (或者真正的数学')但是在不完美的计算机世界中并不等同。
您可以强制执行以下评估顺序:
if (.not. present(x)) then
print*, .false.
else
print*, x
end if
我的标准草案副本包括
条款7.1.5.4.2 评估逻辑内在操作
一旦建立了逻辑内在操作的解释,就可以了 处理器可以评估逻辑上的任何其他表达式 相当于,只要括号的完整性 表达没有被违反。
我对标准的解释是程序不符合,因为它引用了一个不存在的可选参数。请参阅第12.5.2.12节(1)中的规定。因为.and.
运算符的操作数的评估顺序未定义x
可能在不存在时被引用。