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