Azr*_*000 1 fortran gfortran argument-passing fortran90
我手边有以下程序
program foo
type bar
real, dimension(2) :: vector
end type
type(bar), dimension(3) :: bararray
call doSomething(bararray%vector)
end program
subroutine doSomething(v)
real, dimension(3,2), intent(inout) :: v
...
end subroutine
Run Code Online (Sandbox Code Playgroud)
现在这给了我一个编译错误.
Error: Two or more part references with nonzero rank must not be specified at (1)
Run Code Online (Sandbox Code Playgroud)
如果我将呼叫更改为
call doSomething((/bararray%vector(1), bararray%vector(2)/))
Run Code Online (Sandbox Code Playgroud)
一切顺利.问题是,这似乎有点麻烦,所以问题是,是否还有其他方法来编写子程序的参数?
提前致谢.
产生错误是因为在语言中存在约束(在F2008中语法规则是C618),其中结构组件(或类似的多部分参考)中的仅一个部分可能具有非零等级.您对bararray%vector结构组件的引用有两个非零等级 - 组件vector和变量bararray.
(在"更改调用"方法中,对组件向量的引用具有下标,该下标给予该部分整体排名为零,因此接受bararray%vector(1).)
"改变呼叫"方法存在重大潜在问题.
子程序中的伪参数是INTENT(INOUT).这需要实际的论证是可定义的(一个实际上可以"改变"的变量).
在"更改调用"方法中,与该伪参数关联的实际参数是表达式 - 数组构造函数.表达式是不可定义的 - 评估它们的结果是一个值,而不是可以"定义"的东西 - 即你不能理智地说2 + 2 = 6.
据推测,在实际代码中,doSomething子例程是一个外部过程,因此您的编译器尚未对此进行诊断.如果doSomething有一个显式接口(因为它可能在一个模块中),那么我希望编译器报告错误.
其他人建议在调用之前重新编组数据的方法(将数据复制到适当大小的数组变量中,调用过程,复制数据).重写子程序的接口以获取bar类型的对象(移动到模块的类型的定义)显然是另一种可能性.派生类型不仅是存储数据的便捷方式,它们通常是处理数据的便捷方式.
我会非常警惕尝试欺骗处理器接受你"知道" bararray%vector内存中假设数组布局的方法.类型和数组的布局可以在处理器之间变化,加上处理器错误检查可以改善这种技巧,可能导致以后的诊断.供应商提供的库可以摆脱这种伎俩,但不仅仅是编程凡人.
Intel Fortran(13.0.xxx)编译器给出了错误
error #6159: A component cannot be an array if the encompassing structure is an array.
Run Code Online (Sandbox Code Playgroud)
我认为你的问题的答案是,调用一个带有real, dimension(3,2)参数的子程序的正确方法是给该死的东西一个real, dimension(3,2)参数,这需要在调用子程序之前以某种方式编组你的数据.是的,这有点麻烦,但不是严格的类型检查有一个很好的功能?
您可以沿着以下行定义包装器子例程:
subroutine wrapDoSomething(abar)
type(bar), dimension(:), intent(inout) :: abar
...
... marshal your data ...
call subroutine doSomething(marshalled_data)
...
end subroutine wrapDoSomething
Run Code Online (Sandbox Code Playgroud)
我怀疑如果你定义subroutine doSomething没有一个明确的接口,你可能会失去传递它的调用者认为是一个bars 的数组,但子程序得到的是reals 的rank-2数组.如果这不能直接使用块,可能会使用BIND(C)类型定义,这可能会欺骗编译器为6个实数分配连续存储.
如果这一切都在你的脸上爆炸,你是独立的,我的参与将被拒绝.
| 归档时间: |
|
| 查看次数: |
1011 次 |
| 最近记录: |