我想知道编写以下代码的正确方法是什么?
PROGRAM foo
INTEGER :: x
REAL(KIND=8), TARGET, DIMENSION(0: 10) :: array
REAL(KIND=8), POINTER, DIMENSION(:) :: ptr
ptr => array
CALL bar(ptr)
END PROGRAM foo
SUBROUTINE bar (ptr)
REAL(KIND=8), POINTER, DIMENSION(:) :: ptr
INTEGER x
DO x =0, 10
ptr(x) = 2 // seg faults
ENDDO
END SUBROUTINE bar
如果我在ptr
中将bar
声明为REAL(KIND=8), DIMENSION(0:10)
,则此功能正常。但总的来说,我可能不知道传入数组的大小,那么有没有办法将ptr
声明为指向某个数组的指针?我正在使用gfortran
答案 0 :(得分:2)
如果一个过程的伪参数是一个指针,那么任何调用范围都需要一个显式接口。
(有很多东西需要显式接口,指针虚拟只有一个。)
您可以通过在主程序中放置子程序的接口块来自己提供该显式接口。一个替代的,远,远,更好的选择是将子例程放在一个模块中,然后在主程序中使用该模块。第三种方法是使子程序成为调用范围的内部过程。
从Fortran 2003开始,如果你打算将指针指向不同的东西,你应该只使用指针。如果你只是将指针用于一些真正表现得像值的东西,那么你应该使用allocatables。
答案 1 :(得分:2)
这取决于你对“正确”方式的意思。正如IanH已经pointed out,你需要一个显式接口(最好通过在模块中打包)并使用allocatables而不是指针,如果可能的话。
我还要补充一点,如果您不想在子程序中更改数组的分配状态,但只想操纵其元素,那么在子程序中使用一个简单的假定形状数组。下面你会找到一个有效的例子。还有一些事项需要注意:
不要使用real(kind=8)
,因为并非所有编译器都使用字节数作为实数的种类。如果您想要双精度准确度,请按以下方式明确要求。
如果您只想填充具有常量值的数组,请按以下简单方式执行:array(:) = 2.0_dp
这里的例子是:
module accuracy
implicit none
integer, parameter :: dp = kind(1.0d0)
end module accuracy
module barmodule
use accuracy
implicit none
contains
subroutine bar(array)
real(dp), intent(inout) :: array(:)
integer :: ii
do ii = 1, size(array)
array(ii) = ii
end do
end subroutine bar
end module barmodule
program foo
use accuracy
use barmodule
implicit none
real(dp), dimension(0:10) :: array
call bar(array)
end program foo