我正在尝试使用Fortran 77编写的一些旧代码进行现代化。最终,我的目标是让它符合F90 +,但是现在我还在尝试理解它的各个部分。
我已经添加了implicit none
并明确指定了每个变量,删除了90%的goto
语句,使循环更清晰,并重新组织了许多其他内容。我目前的问题是我不完全理解如何使用cray指针来分配内存。例如,我看到类似的内容:
integer :: nx1, nz
integer :: x1, z
pointer ( ptr_x1, x1(1) )
pointer ( ptr_z, z(1000) )
...
ptr_x1 = proprietary_malloc(nx1*SIZEOF_INTEGER)
ptr_z = proprietary_malloc(nz *SIZEOF_INTEGER)
...
proprietary_free(ptr_x1)
proprietary_free(ptr_z)
请注意,proprietary_malloc
应该是c
malloc
的包装器,并带有一些基本的内部内存检查功能。我很有信心代码应该在退出之前调用free
(原始的F77代码根本就没有...),所以我已经添加了自己进入上面的例子。
如果我理解正确,在第一个malloc
语句之后,x1
可以用作nx1
整数数组。但是在第二个声明之后z
呢?有人可以清楚地向我解释这是如何动态分配内存的吗?我更习惯于allocate
或c++
new
陈述...
如果您需要该信息,我会使用ifort
进行编译。谢谢你的帮助。
答案 0 :(得分:3)
[简答]我认为z
可以用作nz
整数的数组,如果我们忠实地翻译原始代码,将它们分配为
integer, allocatable :: x1(:), z(:)
allocate( x1( nx1 ), z( nz ) )
由于原始代码中的z
索引最多可能达到1000,因此确保nz >= 1000
可能更安全。
[长答案]根据这些页面(1,2,3,4),pointer( ptr, a( n1, n2, ... ) )
之类的声明告诉编译器访问记忆从ptr
开始为a( 1:n1, 1:n2, ... )
;即,n1
,n2
,...表示数组维度而不是起始索引。在以下示例中,a(1)
,b(1)
,c(1)
,d(1)
的所有内容都映射到pool(3)
program main
implicit none
integer pool( 5 )
integer :: a, b, c, d
pointer ( p, a( 5 ) ), ( p, b( 10 ) ), ( p, c( * ) ), ( p, d( 1 ) )
pool = [ 1, 2, 3, 4, 5 ]
p = loc( pool( 3 ) )
print *, "a: ", a( 1:5 )
print *, "b: ", b( 1:5 )
print *, "c: ", c( 1:5 )
print *, "d: ", d( 1:5 )
end
所以给予(gfortran -fcray-pointer
)
a: 3 4 5 0 275788968
b: 3 4 5 0 275788968
c: 3 4 5 0 275788968
d: 3 4 5 0 275788968
实际上,Cray指针的关联规则看起来与伪参数非常相似,例如:
program main
implicit none
integer pool( 5 )
pool = [ 1, 2, 3, 4, 5 ]
call sub( pool(3), pool(3), pool(3), pool(3) )
end
subroutine sub( a, b, c, d )
implicit none
integer a( 5 ), b( 10 ), c( * ), d( 1 )
print *, "a: ", a( 1:5 )
print *, "b: ", b( 1:5 )
print *, "c: ", c( 1:5 )
print *, "d: ", d( 1:5 )
end
给出了相同的结果。我们注意到所有a
,b
,c
,d
访问内存超出物理分配的内存(池(1:5)),因此显示了垃圾数据最后两个要素。此外,print *, d( 1:5 )
违反了声明的尺寸d(1)
,可以使用gfortran -fcheck=all ...
等选项进行检查。
现在回到OP的程序,ptr_x1
和ptr_z
获得从类似malloc的例程(nx1
和nz
整数)获得的物理地址),所以我想只要x1
和z
被赋予适当的值,就可以分配nx1
和nz
这些大小。