Fortran传递函数从源数据获得不同的值

时间:2012-09-26 13:10:20

标签: fortran

我想达到以下目标:

  

使用自定义类型数据(例如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的一部分。它是各种封装。用户可以免于输入"%"。

2 个答案:

答案 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