我手边有以下程序
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
现在,这给了我一个编译错误。
Error: Two or more part references with nonzero rank must not be specified at (1)
如果我改变调用
call doSomething((/bararray%vector(1), bararray%vector(2)/))
一切都工作地非常好。 问题是,这只是似乎有点麻烦,所以问题是,是否有任何其他方式来写的子程序的说法?
提前致谢。
误差的产生是因为存在这样只有一个在结构组分(或类似的多部分参考)部分可以具有非零的秩的语言的约束(在F2008的语法规则是C618)。 参考bararray%vector
到所述结构部件具有两个部分具有非零秩-组件vector
和可变bararray
。
(在“改变呼叫”的方式来向矢量的分量的参考文献中有一个下标,给该部分为零的整体等级,因此bararray%载体(1)被接受。)
有一个与“改变呼叫”办法中一个显著的潜在问题。
在子程序中伪参数是INTENT(INOUT)
这需要实际参数是可定义的(实际上可以是“变化”的变量)。
在你的“改变呼叫”接近与伪参数关联的实际参数是一个表达式 - 数组构造。 表达式是没有定义的-进行评价,结果是价值,不是一件可以“定义” -即你不能说三立2 + 2 = 6
。
想必在实际的代码中的doSomething子程序是外部程序,所以你的编译器还没有确诊此。 如果DoSomething的有一个明确的接口(因为它是在一个模块中,也许),那么我会期望编译器报告错误。
也有人建议的重新编组数据呼叫之前的方法(复制数据到适当的大小的数组变量,调用程序,将数据复制出)。 重写子程序的接口取型杆(具有移动到一个模块类型的定义)的对象是明显的另一种可能性。 派生类型不仅是存储数据的一种方便的方式,他们往往使用数据的简便方法。
我会非常警惕的是试图处理器诱骗接受你“知道”是假想的阵列的布局方法bararray%vector
在内存中。 的类型和数组的布局可以从处理器改变为处理器,连同处理器错误检查的改善可以导致后来诊断那种特技的。 供应商提供的库可以摆脱那种把戏,但不是我们这些凡人编程。
英特尔Fortran(13.0.xxx)编译器会发出错误
error #6159: A component cannot be an array if the encompassing structure is an array.
我想回答你的问题是,调用一个子程序这需要一个适当的方式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
我怀疑,如果你定义subroutine doSomething
没有明确的接口,你可以摆脱它传递什么呼叫者认为是数组bar
秒,但什么子程序得到的秩2阵的real
秒。 如果不直摸出块,也许使用BIND(C)
在你的类型定义,这可能会欺骗编译成6张实数分配连续的存储。
如果这一切在你的脸上吹了,你对你自己的,我在这一使命的参与将被拒绝。