gpt4 book ai didi

fortran - 作为派生类型组件的指针

转载 作者:行者123 更新时间:2023-12-02 10:28:29 26 4
gpt4 key购买 nike

我从这个答案( Fortran copy of pointer )中了解到,我应该尝试使用可分配数组而不是数组指针作为派生类型的组件。我打算这样做,但明年我会被锁定在当前的代码中,并且需要能够使用它并理解它,直到明年我可以做出更大更好的更改。

我还认为这个问题具有一定的普遍意义,因为我认为 Fortran 的行为虽然显然是正确的,但相当不直观。因此,更好地理解它的工作原理和原因可能很有值(value)(否则我认为编译器根本不会让我们这样做,对吧?)。

抱歉,介绍有点长。我将尝试将其作为一个已尽可能精简的带注释的程序来完成:

program main

type tRet
real :: agi
real :: wages_tgt(5) ! compiler won't let me declare as
! target but later I point to this
real, pointer :: wages(:)
end type tRet

type(tRet), target :: ret ! I don't quite understand
type(tRet), target :: orig1, orig2 ! why but compiler insists
! these be targets
ret%wages => ret%wages_tgt(1:1)
ret%wages = (/ 11. /)
orig1 = ret
ret%wages = (/ 99. /)
orig2 = ret

这是程序的上半部分,下面是一些结果,打印输出显示为右侧的注释:

   ! This is not want I want and I was surprised, but it is kind
! of explained in the other answer why this happens, so OK...

print *, "orig1%wages ", orig1%wages ! 99.
print *, "orig2%wages ", orig2%wages ! 99.


! But if I copy from orig1 or orig2 into ret then it
! works like I wanted it to work in the first place!
! But I don't completely understand why it works...

ret = orig1
print *, "ret%wages ", ret%wages ! 11.
print *, "orig1%wages ", orig1%wages ! 11.
print *, "orig2%wages ", orig2%wages ! 11.

ret = orig2
print *, "ret = orig2 "
print *, "ret%wages ", ret%wages ! 99.
print *, "orig1%wages ", orig1%wages ! 99.
print *, "orig2%wages ", orig2%wages ! 99.

end program main

我很高兴对这里发生的事情有任何很好的解释。我想,讽刺的是,我并不那么担心为什么这是一个坏主意,而是为什么我的解决方法似乎工作正常?

或者总结我的问题的最简单方法可能是:什么到底指向什么?

编译器:GNU Fortran (GCC) 4.8.5 20150623(Red Hat 4.8.5-16)

最佳答案

这里发生的情况是,当您复制派生数据类型时,派生类型的每个组件都会发生不同的情况。当您执行orig1 = ret时:

  • 已声明的数组(例如 wages_tgt)会被分配新值。这相当于说 orig1%wages_tgt = ret%wages_tgt。这些数组中的每一个都在内存中占据单独位置。
  • 诸如工资之类的指针,被设置为指向源指针当前指向的位置。这相当于说orig1%wages => ret%wages。这两个指针的目标是内存中的相同位置。在此示例中,任何 wages 所指向的内存中的唯一位置是 ret%wages_tgt

考虑到这一点,你的结果对我来说很有意义。添加一些选择性的附加注释:

ret%wages => ret%wages_tgt(1:1)

ret%wages = (/ 11. /) ! so wages_tgt = 11 also

orig1 = ret ! This is BOTH a copy and re-point
! * orig1%wages_tgt = ret%wages_tgt (11)
! * orig1%wages => ret%wages_tgt

ret%wages = (/ 99. /) ! this changes ret%wages & ret%wages_tgt
! to 99 and also orig1%wages since it is
! also pointing to ret%wages_tgt.

! note that orig1%wages_tgt is UNCHANGED
! (still 11) but nothing is pointing to it!

下面的代码...

ret = orig1  ! ret%wages_tgt = orig1%wages_tgt (11) 
! no repointing actually happens this time b/c we have
! set up a circular relationship between all the
! pointers such that ALL of them point to ret%wages_tgt

关于fortran - 作为派生类型组件的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48675618/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com