指向参数数组目标的 Fortran 指针
Fortran pointer to parameter array target
我在一个模块中有几个不同名称的参数数组:
real*8, parameter :: para1(*) = [43.234, 34.0498, ...
real*8, parameter :: para2...
在此模块的例程中
subroutine sub(n,...
...
end
我想在 n=1
时使用 para1
,在 n=2
时使用 para2
,等等。有一些解决方案,一个是制作一个数组 paras= [para1,para2...] 并正确索引,效果很好。但我想尝试使用指针
real*8, pointer :: ptr(:)
并根据n
分配给不同的参数数组,但问题是“PARAMETER attribute conflicts with TARGET attribute at (1)
”。如果我删除 parameter
属性,则例程不那么安全,并且假定 SAVE
属性。
我是不是遗漏了什么或者为什么我们不能合并 parameter
和 target
?是否有解决此问题的好方法?
parameter
和target
属性确实有冲突。具有 target
属性的对象必须是变量(Fortran 2018 8.5.17,C861);命名常量(具有 parameter
属性的对象)不是变量(F2018、8.5.13、C850)。
然后,要使用目标数组,您必须使用变量。拥有一个 "safe" 的变量是很棘手的,因为它的值被编程错误等修改了。有几个注意事项禁止变量出现在 变量定义上下文 中。如果你能安排这样的状态,那么编译器可能有机会检测到你的错误。这很容易发生吗?
在纯过程和 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
受到保护,这些值不会在模块外被修改pars
? las,即使这是真的也无济于事:受到保护,我们甚至不能将指针指向模块变量。
总而言之,您的编译器不会轻易检测到修改变量目标数组的编程错误,因此如果您想使用数组作为目标,则必须小心。
根据@ja72 在评论中的建议,这是对参数使用单个二维数组的尝试。这适用于 gfortran-8.2(在 MacOS10.11 上)。
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
但是,由于代码变得有点复杂(因为重塑)并且可能不适用于旧的编译器,所以使用 non-parameter 数组可能会更直接...
我在一个模块中有几个不同名称的参数数组:
real*8, parameter :: para1(*) = [43.234, 34.0498, ...
real*8, parameter :: para2...
在此模块的例程中
subroutine sub(n,...
...
end
我想在 n=1
时使用 para1
,在 n=2
时使用 para2
,等等。有一些解决方案,一个是制作一个数组 paras= [para1,para2...] 并正确索引,效果很好。但我想尝试使用指针
real*8, pointer :: ptr(:)
并根据n
分配给不同的参数数组,但问题是“PARAMETER attribute conflicts with TARGET attribute at (1)
”。如果我删除 parameter
属性,则例程不那么安全,并且假定 SAVE
属性。
我是不是遗漏了什么或者为什么我们不能合并 parameter
和 target
?是否有解决此问题的好方法?
parameter
和target
属性确实有冲突。具有 target
属性的对象必须是变量(Fortran 2018 8.5.17,C861);命名常量(具有 parameter
属性的对象)不是变量(F2018、8.5.13、C850)。
然后,要使用目标数组,您必须使用变量。拥有一个 "safe" 的变量是很棘手的,因为它的值被编程错误等修改了。有几个注意事项禁止变量出现在 变量定义上下文 中。如果你能安排这样的状态,那么编译器可能有机会检测到你的错误。这很容易发生吗?
在纯过程和 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
受到保护,这些值不会在模块外被修改pars
? las,即使这是真的也无济于事:受到保护,我们甚至不能将指针指向模块变量。
总而言之,您的编译器不会轻易检测到修改变量目标数组的编程错误,因此如果您想使用数组作为目标,则必须小心。
根据@ja72 在评论中的建议,这是对参数使用单个二维数组的尝试。这适用于 gfortran-8.2(在 MacOS10.11 上)。
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
但是,由于代码变得有点复杂(因为重塑)并且可能不适用于旧的编译器,所以使用 non-parameter 数组可能会更直接...