Fortran增加了函数中的动态数组大小

Mat*_*009 7 fortran

我需要在Fortran中使用可变大小的数组.在C++中我会使用vector.所以我有一个像这样的功能

integer function append(n, array, value)
  integer, pointer, dimension(:) :: array
  integer, pointer, dimension(:) :: tmp_arr
  integer n

  if (size(array) .eq. n) then
     allocate(tmp_arr(2*size(array)))
     tmp_arr(1:size(array)) = array
     deallocate(array)
     array => tmp_arr
  end if
  n = n + 1
  array(n) = value
  append = n
end function
Run Code Online (Sandbox Code Playgroud)

如果我按照它的方式使用它可以正常工作

integer pos, val
pos = append(n, array, val)
Run Code Online (Sandbox Code Playgroud)

但是,如果我想用它的方式

integer i,j,n ! i,j<n
array(i) = append(n, array, array(j))
Run Code Online (Sandbox Code Playgroud)

与gfortran这不起作用.它编译,但段错误.问题似乎是gfortran从数组(i)和数组(j)中创建地址,将后者发送到函数append,然后当访问数组(j)的地址并且写入数组(i)时,地址空间已被解除分配.

我想要的是将数组(j)的值放在堆栈(而不是地址)上然后在函数中使用,并在函数完成后查找数组(i)的uptodate地址并查看结果保存的功能.

我很确定gcc会按照我想要的方式来做,为什么gfortran如此吝啬?

在Fortran中是否有任何方法可以使一个强大的(意味着数组(j)= ...示例工作)函数或数据类型具有类似行为的c ++ stl向量?

结论:

我最终介绍了临时变量

integer tmp_val
tmp_val = value
...
array(n) = tmp_val
Run Code Online (Sandbox Code Playgroud)

所以至少这个方法可以称为

pos = append(n, array, array(j))
array(i) = pos
Run Code Online (Sandbox Code Playgroud)

并希望该项目的其他/未来开发人员不会试图"优化"这两条线以消除'pos'的必要性.

感谢您的回答和评论.

jan*_*neb 12

IRO-bot的答案是Fortran 90的正确方法.如果您可以将自己限制为支持Fortran 2003 MOVE_ALLOC内在的编译器(自4.2版本以来包含在gfortran中),您可以避免使用其中一个副本.也就是说,将数组的大小增加2倍可以写为


allocate(tmp_arr(2*size(array)))
tmp_arr(1:size(array)) = array
deallocate(array)
move_alloc(tmp_arr, array)
! tmp_arr is now deallocated
Run Code Online (Sandbox Code Playgroud)


mil*_*cic 9

好的,问题是您无法释放并重新分配要为其分配函数值的数组.你对问题的原因是正确的(参考传递的参数而不是C中的值).由于您在函数体内释放数组,因此对该数组的赋值变为无效,从而导致段错误.这不是一个gfortran问题,尝试使用ifort和pgf90,所有这些都报告了同样的问题.这对我有用:

PROGRAM dynamic_size
INTEGER,DIMENSION(:),ALLOCATABLE :: array

ALLOCATE(array(10))

array=(/1,2,5,7,4,3,6,5,6,7/)

WRITE(*,*)SIZE(array)
CALL resize_array
WRITE(*,*)size(array)

CONTAINS

SUBROUTINE resize_array
INTEGER,DIMENSION(:),ALLOCATABLE :: tmp_arr

ALLOCATE(tmp_arr(2*SIZE(array)))
tmp_arr(1:SIZE(array))=array
DEALLOCATE(array)
ALLOCATE(array(size(tmp_arr)))
array=tmp_arr

ENDSUBROUTINE resize_array

ENDPROGRAM dynamic_size
Run Code Online (Sandbox Code Playgroud)