类型数组作为函数参数内阵列(Array inside type array as function

2019-09-30 04:50发布

我手边有以下程序

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)/))

一切都工作地非常好。 问题是,这只是似乎有点麻烦,所以问题是,是否有任何其他方式来写的子程序的说法?

提前致谢。

Answer 1:

误差的产生是因为存在这样只有一个在结构组分(或类似的多部分参考)部分可以具有非零的秩的语言的约束(在F2008的语法规则是C618)。 参考bararray%vector到所述结构部件具有两个部分具有非零秩-组件vector和可变bararray

(在“改变呼叫”的方式来向矢量的分量的参考文献中有一个下标,给该部分为零的整体等级,因此bararray%载体(1)被接受。)

有一个与“改变呼叫”办法中一个显著的潜在问题。

在子程序中伪参数是INTENT(INOUT) 这需要实际参数是可定义的(实际上可以是“变化”的变量)。

在你的“改变呼叫”接近与伪参数关联的实际参数是一个表达式 - 数组构造。 表达式是没有定义的-进行评价,结果是价值,不是一件可以“定义” -即你不能说三立2 + 2 = 6

想必在实际的代码中的doSomething子程序是外部程序,所以你的编译器还没有确诊此。 如果DoSomething的有一个明确的接口(因为它是在一个模块中,也许),那么我会期望编译器报告错误。

也有人建议的重新编组数据呼叫之前的方法(复制数据到适当的大小的数组变量,调用程序,将数据复制出)。 重写子程序的接口取型杆(具有移动到一个模块类型的定义)的对象是明显的另一种可能性。 派生类型不仅是存储数据的一种方便的方式,他们往往使用数据的简便方法。

我会非常警惕的是试图处理器诱骗接受你“知道”是假想的阵列的布局方法bararray%vector在内存中。 的类型和数组的布局可以从处理器改变为处理器,连同处理器错误检查的改善可以导致后来诊断那种特技的。 供应商提供的库可以摆脱那种把戏,但不是我们这些凡人编程。



Answer 2:

英特尔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张实数分配连续的存储。

如果这一切在你的脸上吹了,你对你自己的,我在这一使命的参与将被拒绝。



文章来源: Array inside type array as function argument