gfortran和ifort(可分配数组和全局变量)之间的编译器差异 代码
下面的MWE描述了我想要使用的东西(请注意,我没有设计这个,我只是尝试使用一些人的代码,我通常不会使用全局变量) 问题 gfortran给出了一个错误,该错误读取gfortran和ifort(可分配数组和全局变量)之间的编译器差异 代码,fortran,gfortran,intel-fortran,Fortran,Gfortran,Intel Fortran,下面的MWE描述了我想要使用的东西(请注意,我没有设计这个,我只是尝试使用一些人的代码,我通常不会使用全局变量) 问题 gfortran给出了一个错误,该错误读取错误:变量'n'不能出现在表达式中的(1),指向函数中的实数(8)::a(n,3)。 在一个子程序中,它会工作,那么这里可能有什么问题 问题 为什么ifort(15.0.3版)编译了这个,而gfortran(4.8.4版)没有编译呢?我认为这可能是一个解释,尽管像@VladimirF一样,我实际上无法回忆或找到标准的相关部分(如果有)
错误:变量'n'不能出现在表达式中的(1)
,指向函数中的实数(8)::a(n,3)
。
在一个子程序中,它会工作,那么这里可能有什么问题
问题
为什么ifort(15.0.3版)编译了这个,而gfortran(4.8.4版)没有编译呢?我认为这可能是一个解释,尽管像@VladimirF一样,我实际上无法回忆或找到标准的相关部分(如果有) 这条线
real(8) :: a(N,3)
声明函数的结果是一个名为a
的数组。这掩盖了主机关联引用数组a
的相同名称的可能性。功能范围内的a
不是程序范围内的a
声明维度依赖于变量值的数组,例如a(N,3)
,要求在编译时变量的值是已知的(或至少是已知的)。在这种情况下,在主机作用域中指定属性参数可以解决问题。虽然这并不能解决糟糕的设计问题,但OP似乎在这一点上束手无策
英特尔编译器编译这个并不奇怪,它编译了它的祖先多年来为了向后兼容而编译的各种奇怪的东西
我只提供了这个半生不熟的解释,因为经验告诉我,一旦我这样做,一位真正的Fortran专家(伊恩,弗朗西斯卡勒斯,(通常是)弗拉基米尔)会非常愤怒,以至于发布更正,我们都会学到一些东西。正如其他人所评论的那样,很难说某些东西是否被明确允许:这种语言主要是基于规则和限制来进行限制的
因此,我不会证明代码没有错误(并且不允许gfortran拒绝它),但让我们看看发生了什么
首先,我将反对由给出的一件事,因为这稍微相关:
声明维度依赖于变量值的数组,例如a(N,3)
,要求在编译时变量的值是已知的(或至少是已知的)
显式形状数组的边界不一定总是由常量表达式给出(我们松散地定义为“编译时已知/可知”):在某些情况下,显式形状数组可以由变量给出边界。这些对象称为自动对象(以及规范表达式给出的边界)
函数结果就是允许自动对象的地方。在函数结果声明的问题示例中,N
与主机关联并形成规范表达式
与其穷尽所有其他约束以确保a
的声明确实被允许,不如让我们看看gfortran如何响应程序的小修改
首先,gfortran对象的问题代码的精简版本
integer n
contains
function f() result(g)
real g(n)
end function f
end program
f
的函数结果的名称为g
。无论我们如何调用函数结果,当我们调用它时会发生什么
integer n
contains
function f()
real f(n)
end function f
end program
这对我来说是一件愉快的事情
如果我们在模块中而不是在主程序中构建第一个块会怎么样
module mod
integer n
contains
function f() result(g)
real g(n)
end function f
end module
这也可以编译
自然的结论是:即使gfortran拒绝第一个代码是正确的(我们忽略了一些隐藏得很好的约束),它要么在不拒绝其他代码方面存在严重的不一致性,要么约束非常奇怪。Solaris Studio也接受这一点。我在标准中找不到任何禁止这样做的东西,但人们可能总是忽略了一些东西。可能值得向gfortran开发人员展示。很难确认标准中是否允许某些内容。通常情况下,我们必须确认没有任何东西禁止这样做,但搜索这样的案例是困难的。我几天前在comp.lang.fortran上问过这一问题,Steve Kargl(gfortran开发者)同意这是一个gfortran bug。我只是没有时间写一份报告。
module mod
integer n
contains
function f() result(g)
real g(n)
end function f
end module