Pointers Fortran指针的深度副本
我想从Pointers Fortran指针的深度副本,pointers,fortran,fortran-iso-c-binding,Pointers,Fortran,Fortran Iso C Binding,我想从c\u f\u pointer中保留一份生成的fortran指针的深度副本,以便进行检查等等 (编辑1:我使用“deepcopy”作为“制作独立于原件的副本” a = (/1,2,3,4/) a_deepcopy = a a_deepcopy(2) = 1 在上面的示例中,原始的a保持(/1,2,3,4/),而a\u deepcopy更改为(/1,1,3,4/)。如果它不是deepcopy,更改a_deepcopy的元素也会更改它原来的a的元素。我使用
c\u f\u pointer
中保留一份生成的fortran指针的深度副本,以便进行检查等等
(编辑1:我使用“deepcopy”作为“制作独立于原件的副本”
a = (/1,2,3,4/)
a_deepcopy = a
a_deepcopy(2) = 1
在上面的示例中,原始的a
保持(/1,2,3,4/)
,而a\u deepcopy
更改为(/1,1,3,4/)
。如果它不是deepcopy,更改a_deepcopy
的元素也会更改它原来的a
的元素。我使用“deepcopy”一词只是因为我在Python上下文中见过这种命名。)
我在谷歌上搜索了很多fortran指针指向可分配数组的deepcopy示例,有人可能已经质疑过这个主题,但找不到合适的
以下将指针
复制到可分配
的代码编译并运行良好,以便在“可分配A2”数组中生成“指针p”的deepcopy,但根据我前面问题的答案,我知道我最好小心地以某种混合方式处理指针
和可分配
,即使它们似乎工作正常
program pointer3
implicit none
real*8,allocatable :: A2(:)
real*8,target :: A(4)
real*8,pointer :: P(:)
A = 3.1416d0
P => A
allocate ( A2(size(A,1)) )
A2 = P # Assign 'pointer' to 'allocatable'
print *, 'Initially'
write(*,'(a, 4f6.2)') 'A ', A
write(*,'(a, 4f6.2)') 'P ', P
write(*,'(a, 4f6.2)') 'A2', A2
P(2) = 1.d0
print *, 'After'
write(*,'(a, 4f6.2)') 'A ', A
write(*,'(a, 4f6.2)') 'P ', P
write(*,'(a, 4f6.2)') 'A2', A2
end program
问题是
上述代码是否正确地将指针
复制到可分配
数组中
如果我使用普通fortran指针
及其目标
,我会尝试将其深度复制到可分配
数组,只需将其目标
属性分配到可分配
,如下所示(尽管我不能这样做,因为我使用的是c_f_指针
,而等效的目标
是c_ptr
,它不是fortran数组)
第一次尝试将指针直接分配到可分配数组时,这很好,但这似乎很奇怪,因为显然“a”和“A2”的类型不同:real*8,allocatable
和real*8,target
我认为上面两种制作fortran指针
深度复制的方法都不合适,也不安全。我如何才能以安全可靠的方式制作指针
的深度复制
感谢您阅读此问题。开头有一句警告:指针可能有用,但也非常危险,因为很容易产生非常模糊且难以调试的错误
我不记得有那么多的案例,我真诚地想:是的,这里的指针是个好主意(尽管有一些)
让我们从讨论数组开始:普通数组必须在编译时声明其形状,如下所示:
INTEGER :: A(10)
这导致程序在内存中留出一个区域来存储十个整数值
但您并不总是知道在编码时数组实际必须有多大。这就是Fortran引入可分配数组的原因。代码不是在开始时声明它们的形状,而是告诉编译器应该准备好以后需要内存
INTEGER, ALLOCATABLE :: A(:)
这告诉编译器它需要一个整数数组,但它还不知道它有多大。然后,当程序运行并计算出它需要多大的数组时,您可以使用ALLOCATE
命令实际创建内存:
ALLOCATE(A(100))
只有在对数组调用了ALLOCATE
之后,才能真正使用它。(实际上,使用可分配数组还有更多的原因,但我现在还不详细介绍。)
指针是不同的。指针不存储值,而是存储值所在的内存地址。因此,在实际与值交互之前,首先需要执行以下两项操作之一:
将指针指向目标,例如:
P => A
分配指针指向的内存:
ALLOCATE(P)
您可以看到,它也使用了ALLOCATE
命令,但使用方式略有不同:当您分配一个可分配数组时,您将直接分配的内存与该数组相关联。当您分配一个指针时,您分配内存,然后将该内存的地址写入与指针关联的内存中
话虽如此,让我们来看看你在做什么:
A
或多或少是一个普通数组,除了关键字target
告诉编译器应该可以让指针指向该数组之外。
将此数组的所有元素设置为一个值
p
是指向数组的指针。您将p
指向a
,这意味着这两个指针现在在完全相同的内存上工作。更改一个,另一个也会更改
然后为A2
分配内存A2
就像任何其他数组一样,它与A
或p
无关
因为p
和A
引用相同的内存,所以这两行具有相同的效果:
A2 = A
A2 = P
在这两种情况下,数组A
的内容都会复制到A2
的内存中。然后,更改A
中的任何值(无论您是使用A
还是p
来执行此操作都无关紧要)也将在P
中显示为更改。但是A2
的值不会更改:它们存储在其他地方
用指针思考真的很难。当我真的必须这样做时,我通常会事先在一张纸上画出过程,这样我就可以跟踪哪个指针在什么时候指向哪里
在Fortran中,您通常不需要指针。没有指针,每个副本都是您所说的“深度副本”。请不要使用非标准、不可移植的real*8,它不是Fortran的一部分,也从来不是Fortran的一部分。请看。在您的问题中,您能否定义“深度副本”的含义-我不认为你没有用它
P => A
ALLOCATE(P)
A2 = A
A2 = P