我有一些遗留的Fortran 77代码,我试图至少在没有警告的情况下进行编译(不禁用警告)。有子程序调用传递标量,其中子程序需要一个数组,因为标量用作size-1数组,这不会导致任何问题。但是使用英特尔编译器,如果我启用接口警告,我会收到错误:
error #8284: If the actual argument is scalar, the dummy argument shall be scalar unless the actual argument is of type character or is an element of an array that is not assumed shape, pointer, or polymorphic.
在某些情况下,我试图通过使用数组和标量变量重载子例程来解决这个问题,但是当传递的参数是“数组的元素”时,我遇到了一个问题,它被检测为标量。考虑以下示例(使用gfortran测试):
program a
integer n,dum(3)
interface readn
subroutine readn_s(n,m)
integer m,n
end subroutine
subroutine readn_a(n,m)
integer m,n(*)
end subroutine
end interface
call readn(n,1)
write(6,*) 'n=',n
call readn(dum,3)
write(6,*) 'dum=',dum
call readn(dum(2),2)
write(6,*) 'dum=',dum
end program
subroutine readn_s(n,m)
integer i,m,n
n=2
end subroutine
subroutine readn_a(n,m)
integer i,m,n(*)
do i=1,m
n(i)=1
end do
end subroutine
readn(dum,3)
来电正确使用readn_a
,而第二个使用readn_s
。预期的行为是两者都应该使用readn_a
。实际上,如果我用readn_a
替换两个电话,一切都符合预期。
当实际参数是数组元素时,是否可以正常工作并使用重载例程的“数组”版本?如果我用readn(dum(2:),2)
调用子程序,我发现它有效,但我担心会创建一个数组的临时副本......
file.f90
program a
integer n,dum(3)
call readn_a(n,1)
write(6,*) 'n=',n
call readn_a(dum,3)
write(6,*) 'dum=',dum
dum=3
call readn_a(dum(2),2)
write(6,*) 'dum=',dum
end program
file2.f90
subroutine readn_a(n,m)
integer i,m,n(*)
do i=1,m
n(i)=1
end do
end subroutine
使用gfortran -Wall file.f90 file2.f90
或ifort file.f90 file2.f90
进行编译,一切正常,输出是预期的:
n= 1
dum= 1 1 1
dum= 3 1 1
与ifort -warn all file.f90 file2.f90
汇编,我得到上面的error #8284
。所以这就是为什么我想要一个可以使用标量或数组的子程序的版本......但是会给数组版本一个数组元素。
答案 0 :(得分:2)
在您尝试的解决方案中,类型排序通用解析将所有数组元素委托给子例程的标量版本,并且不会在数组部分执行预期的工作。所以“预期的行为是两者都应该使用readn_a。”对于你选择的方法是不可能的。
好吧,当您重写代码以传递数组部分时,您可能会注意到这一点。但是我们再次遇到和以前一样的问题,你的例子很简单。我们可以肯定你所展示的例子中没有临时数组,我们绝对不能说你真正的代码。如果你从一些随机的地方开始使用一些2D小节,你肯定会有临时数组,而且可能很难做出正确的小节。
原始警告应该在原始遗留代码中相当容易避免。 FORTRAN 77没有非连续数组,所以如果你保持你的参数为integer :: a(*)
而不是integer :: a
并进一步传递。如果你的原始变量是标量,那就是一个问题。
问题是整数标量不构成元素序列:
F2008 12.5.2.11 1实际参数表示元素序列 if 它是一个数组表达式,一个数组元素指示符,一个默认值 字符标量,或带有C字符的字符标量 善良(15.2.2)。 ...
数组元素指示符a(2)
是元素序列,但标量n
不是。
因此,不允许在传递数组元素时使用的序列关联:
F2008 12.5.2.11 4表示元素的实际参数 序列并对应于数组的伪参数 如果伪参数是伪参数,则与伪参数相关联 显式形状或假定大小的数组。 ...
您的代码并非严格符合Fortran标准,但如果您设法编译它,很可能会按预期工作。
可能的解决方案:
您可以将参数作为数组表达式传递,但可以不在子例程中修改参数
call readn_a([n],1)
您只需禁用有关接口匹配的警告
即可 ifort -warn nointerfaces
您可以创建单独的子程序,这些子程序仅适用于标量并以不同的名称调用它。
您还可以通过英特尔编译器指令
禁用该伪参数的参数检查 !DEC$ ATTRIBUTES NO_ARG_CHECK :: dummy-arg-name