fortran - 分配时Fortran可分配数组的内存位置?

标签 fortran dynamic-memory-allocation

假设我有类似的东西:

real, dimension(:), allocatable :: S
integer, dimension(:) :: idx
...
S = S(idx)

其中 Sidx 在分配之前已正确分配/初始化。

Fortran 标准对 S 的内存位置(地址)有何规定(如果有的话)?分配后它应该留在同一个地方吗?是否未指定(由编译器决定)?如果 S 不是 allocatable 有区别吗?

完整示例:

$ cat test.f90 
program test
implicit none
real, dimension(:), allocatable :: S
integer :: i, idx(7) = [1,3,5,7,2,4,6]

allocate(S(size(idx)))
do i=1,size(S)
  S(i) = i*i
end do

write(6,*) S
write(6,*) loc(S)

S = S(idx)

write(6,*) S
write(6,*) loc(S)

S(:) = S(idx)

write(6,*) S
write(6,*) loc(S)

deallocate(S)

end program

$ sunf90 -V
f90: Studio 12.6 Fortran 95 8.8 Linux_i386 2017/05/30

$ sunf90 test.f90 ; ./a.out 
 1.0 4.0 9.0 16.0 25.0 36.0 49.0
 37518752
 1.0 9.0 25.0 49.0 4.0 16.0 36.0
 37519840
 1.0 25.0 4.0 36.0 9.0 49.0 16.0
 37519840

(假设 loc 给出了与数组地址相关的内容)

最佳答案

在您的示例中,idx 是否具有与 S 相同的范围(元素数量)很重要。如果是,则 S(idx) 的形状与 S 的形状相同,并且标准规定不会发生 S 的重新分配.但是如果它们不同,那么标准会说 S 被释放,然后重新分配为 S(idx) 的形状。如果发生这种重新分配/重新分配,如果基地址保持不变,则无法预测(并且可能不太可能)。

然后你问如果 S 不可分配怎么办 - 在这种情况下,形状 必须 匹配并且它只是数据的副本,尽管可能通过临时数组,因为有重叠。

-- 2019 年 8 月 24 日编辑--

我就此对 J3(美国 Fortran 标准委员会)电子邮件列表进行了调查。共识是,在没有 TARGET 的情况下,“更改地址”是符合标准的,尽管不止一位成员质疑这是否是个好主意。编译器开发人员显然认为分配新存储并执行单个副本比保持相同的存储并执行两个副本(一个到 temp,然后一个返回到 S)更快。我可能认为这是如果要复制大量数据(也许)是有益的,但在较小的情况下则不然。

正如您所发现的,无论如何,您都可以通过为 S 提供 TARGET 属性来禁用此行为。

关于fortran - 分配时Fortran可分配数组的内存位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57606191/

相关文章:

compilation - Fortran 错误 : type mismatch between two unrelated subroutine calls

fortran - 在 Fortran 中读取行数已知但每行条目数未知的数据文件

c++——消失的变量

c - 了解结构中字符串的动态内存分配

C 函数 : is this dynamic allocation? 用变化的长度初始化数组

fortran - Fortran 中的未知大小矩阵

fortran - Fortran 中未调用派生类型的自定义构造函数

python - 不完整的 gamma 函数 : can this code get any faster in cython, C 或 Fortran?

C++ 多态行为 : swapping derived pointer types

c++ - 指针数组分配动态内存