我想达到以下目标:
使用自定义类型数据(例如A)的第一个元素的指针来引用A
我创建了以下代码原型:
program test
implicit none
type foo
integer i
integer j
end type foo
type(foo), target :: a
type(foo) b
integer, pointer :: ai
a%i = 1
a%j = 2
ai => a%i
print *, "Address of a is", loc(a)
b = transfer(ai, b)
print *, "The values of a are:", a%i, a%j
print *, "Address of b is", loc(b)
print *, "The values of b are:", b%i, b%j
end program test
我希望b
的值应与a
相等,但我在计算机中得到了结果
Address of a is 140736918227392
The values of a are: 1 2
Address of b is 140736918227376
The values of b are: 1 0
b%j
的值与a%j
不同。有什么问题?
提前致谢!
编辑:
我的目的是隐藏用户定义的类型(比如foo
),只允许用户访问foo
的第一部分(比如一个数组),当用户提供该数组时,我可以得到休息foo
的一部分。它是各种封装。用户可以免于输入"%"。
答案 0 :(得分:4)
我不确定你是否理解transfer
函数的作用。声明
b = transfer(ai, b)
获取位置ai
中的数据,并使用b
的类型(以及相关的类型)创建它的副本。因此,transfer
用于允许程序例如将实数的位视为整数的位。您的声明所做的是获取ai
处的数据,这是一个整数,并将其更改为type(foo)
,并将其分配给b
。
我认为你很幸运,因为编译器没有抱怨ai
的值没有为transfer
提供足够的位来填充b
。我并不感到惊讶,因为transfer
本质上是一种规避Fortran严格打字的方式。当然,b = 1
之类的直接赋值会导致编译错误,因为lhs和rhs没有兼容的类型。
我认为你有权期望b%j
的价值在你写出来时具有任何特殊价值。根据我的快速调查,您的程序根本不会修改b%j
的值,在您的情况下,它会初始化为0
并且不会被修改。
但我认为真正的问题是你正在尝试做一些Fortran程序员不会做的事情,即使用指向结构的第一个元素的指针作为整个结构的引用。 C和它的堂兄的气味。
在Fortran中,将ai
声明为type(foo), pointer
然后编写诸如
ai => a
...
b = ai
你真的想做什么?如果答案是'使用Fortran编译器在C中编程',那么祝你好运,享受痛苦的世界,那就是收费公路。
答案 1 :(得分:2)
只需添加,
ai => a%i
b = transfer(ai, b)
的意思是,当翻译成C时。
是
b = (foo)(a->i)
如果我对C的记忆不会欺骗我。所以你真的要转换一个整数来输入foo。
<强> - 编辑 - 强> 您可以在结构(派生类型)中包含许多私有组件,模块的用户看不到,但您可以在模块内使用它们。用户可以使用模块中定义的过程与私有实体进行交互。使用较新的编译器,您甚至可以使用C ++中的方法(类型绑定过程)和其他OOP。
module mod
type foo
private
integer,public :: i
integer :: j !is private!
end type
end module mod
program p
use mod
type(foo) :: a,b
b%i = 1
!intrinsic assignment should work, even if you don't see a%j and b%j
!you can also override the assignment yourself
a = b
write(*,*) a%i
end program p