Pointers 指向参数数组目标的Fortran指针
我在一个模块中有几个不同名称的参数数组:Pointers 指向参数数组目标的Fortran指针,pointers,parameters,fortran,gfortran,target,Pointers,Parameters,Fortran,Gfortran,Target,我在一个模块中有几个不同名称的参数数组: real*8, parameter :: para1(*) = [43.234, 34.0498, ... real*8, parameter :: para2... 在本模块的例程中 subroutine sub(n,... ... end 我想在n=1时使用para1,para2当n=2时使用para1,等等。有一些解决方案,一个是制作一个数组paras=[para1,para2…],并正确地索引,这样可以很好地工作。但我想尝试使用指针 real
real*8, parameter :: para1(*) = [43.234, 34.0498, ...
real*8, parameter :: para2...
在本模块的例程中
subroutine sub(n,...
...
end
我想在n=1
时使用para1
,para2
当n=2
时使用para1
,等等。有一些解决方案,一个是制作一个数组paras=[para1,para2…],并正确地索引,这样可以很好地工作。但我想尝试使用指针
real*8, pointer :: ptr(:)
并根据n
将其分配给不同的参数数组,但问题是“参数属性与(1)
处的目标属性冲突”。如果删除参数
属性,则例程的安全性会降低,并假定保存
属性
我是否遗漏了什么,或者为什么我们不能将
参数
和目标
组合起来?对于这一点,有什么好办法吗?参数和目标属性确实冲突。具有target
属性的对象必须是变量(Fortran 2018 8.5.17,C861);命名常量(具有参数属性的对象)不是变量(F2018,8.5.13,C850)
要使用目标数组,则必须使用变量。要让一个变量“安全”地避免其值被编程错误或类似错误修改,这是很棘手的。有几个注意事项禁止变量出现在变量定义上下文中。如果您可以安排这样的状态,那么编译器可能有机会检测到您的错误。这容易发生吗
在纯过程和intent(in)
伪参数之外,最诱人的禁止是使用受保护的模块变量:
module pars
real, save, target, protected :: para1(74) = [...]
real, save, target, protected :: para2(1) = [6]
end module
subroutine sub (...)
use pars
real, pointer :: p
p => para1
end subroutine sub
受到保护后,这些值不会在模块PAR
之外被修改?唉,即使这是真的,也没有什么帮助:由于受到保护,我们甚至不能将指针指向模块变量
总之,编译器不容易发现修改变量目标数组的编程错误,因此,如果要将数组用作目标,必须小心。按照@ja72在注释中的建议,这是一次尝试使用单个2D数组作为参数的尝试。这与gfortran-8.2(在MacOS10.11上)配合得很好
但是,由于代码变得有点复杂(因为重塑),并且可能无法与旧的编译器一起使用,因此仅使用非参数数组可能更简单…是的,您缺少了一些东西。Fortran 2018,约束C860:具有目标属性的实体应为变量。具有参数属性的实体是命名常量。命名常量不是变量。你能为参数使用单个2D数组吗?@ja72它们具有不同的长度,因此构造结构化2D参数数组更为困难。然后您仍然需要存储长度。在1D中,您可以堆叠它们并存储位置,这样就容易多了。似乎您需要一个。@ja72不,我不需要:)而且它不是一个参数。关于2D解决方案,请参见“roygvib”的答案。最后一段有点牵强。在模块外的过程中修改这些模块变量的值是很简单的。比这更糟糕,不是吗?整个target,protected
部分都是胡说八道。你知道目标必须是变量的具体原因吗?@Jonatan,我不能代表标准的作者说话,但有两点:如果指针可以是变量,那么为了简单起见,它指向的任何东西都必须是变量;命名常量不必在“运行时”存在。很好,但1D确实更简单:)
program main
implicit none
integer i
integer, parameter :: para1(*) = [1, 2, 3, 4, 5]
integer, parameter :: para2(*) = [6, 7]
integer, parameter :: N1 = size(para1), N2 = size(para2), N = max(N1, N2)
integer, parameter :: params(N, 2) = &
reshape( [ para1, (0, i = 1, N - N1), &
para2, (0, i = 1, N - N2) ], [N, 2] )
print *, "para1 = ", params( :, 1 )
print *, "para2 = ", params( :, 2 )
print *, "Input i"
read *, i
print *, params( :, i )
end
$ gfortran-8 test.f90 && ./a.out
para1 = 1 2 3 4 5
para2 = 6 7 0 0 0
Input i
1
1 2 3 4 5