回 帖 发 新 帖 刷新版面

主题:[讨论]请问fortran指针何时能够指向地址啊???

请问大家fortran指针何时能够指向地址啊???
现在的版本好像只是给所指对象取了一个别名,还有在fortran中能否像C++一样取出一个变量的地址赋给一个指针变量?

回复列表 (共6个回复)

沙发

指向地址?你是说指向指针的指针?

现在可不止是取个别名。跟C++一样是存储的变量的地址哦亲。只不过使用的时候有一些限制而已。

板凳

啊啊啊,请大侠赐教啊,能够详细一点回答在fortran中怎么用指针吗?我看了以前的帖子,试了两个粒子:

example 1:
PROGRAM main()
   implicit none
   integer, target  :: a=1   ! 声明一个可以当做目标的变量
   integer, pointer :: p     ! 声明一个可以指向整数的指针
   p=>a ! 把指针P指到变量a
   write(*,*) p
   a=2  ! 改变a的值
   write(*,*) p
   p=3  ! 改变指针p指向的内存内容
   write(*,*) a
   write(*,*) p
   stop
end program
运行结果:1 2 3 3

example 2:
PROGRAM main()
   implicit none
    real(8), target :: a(10)
    real(8), pointer :: pa(:) => null()
    a = 10.251d0
    pa =>a
    print*,a
    write (*,*) "sizeof(a) = ",sizeof(a),"Byte"
    write (*,*) "sizeof(pa) = ",sizeof(pa),"Byte"
end program
运行结果:
结果都是80Byte,如果将该例子中的real(8)改成real(4) 则运行结果都为40Byte,如果指针Pa存储的是a的地址那不应该要40Byte那么多啊。

我是初步测试了一下,对fortran指针不懂,请大侠指点,另外在C++中去一个变量的地址可以用&,在fortran中有类似的算符吗,请详细指点下指针怎么用,我想这个很多童鞋都不太清楚,谢谢
[em12][em10][em8][em5]

3 楼

第一个问题:

其实 p 和 pa 都是地址。只不过 sizeof 的用法跟 C 有点差别而已。

如果 sizeof 一个指针,那么返回的,不是指针的大小,而是指向内容的大小。

你认为 p 是一个别名,是一种误解。因为 Fortran 没有 * 操作符,因此 p 完全等同于 C 语言的 *p

通常在 32 位操作系统下,地址是 4 字节的。在 C/C++ 里,他们严格的是 4 字节。

但是 Fortran 不同,Fortran 的指针有可能不是一个简单的地址。可能是一个结构体。

类似

struct P_PointerToArray {
  int Address;
  int Dimension;
  int Size
}

之类的

这个指针,并不单纯的是一个地址,而是一个描述它指向内容的各种参数的结构体。

而这个结构体具体的内容,则语法没有做出规定。各家的编译器都可以自己定义这个结构体。

这是由于 Fortran 语法的特殊性要求的,单纯的地址无法实现。必须同时存储数组的维数,大小,上下限。(请注意,Fortran 的数组可以是 a(10:15) ,不一定从 0 或 1 开始。而 C 语言只能从 0 开始)。因此,一个指针不能单纯是一个地址,必须存储更多的东西,也就是这个结构体。

正因为如此,sizeof( pointer ) 不会返回 4 字节,也不会返回这个结构体的大小(它由编译器自行规定,返回它的大小没有什么意义)。

第二个问题:

Fortran 没有 & 取址操作符。因为 Fortran 的函数子程序间,默认是传址的,而 C 默认是传值的。
因此,严格的说,Fortran 所有的实参,都是“指针”。你在函数中改变虚参,则对应的实参也会改变。

同时,Fortran 对数学计算有着更严格的判断,所以它限制了指针的使用。这是出于对科学计算的严谨考虑,所以它不像 C 那样,它放弃了指针的灵活性。

如果你真的像获得一个变量的内存地址,可以试着使用 loc( a ) , loc( p ) 这样。但是这个函数并非标准函数,是某些编译器的扩展。

第三个问题,
给你一个 Fortran 的简单链表。供你学习。

Program Main 
  Implicit None
  Integer :: iCount , i
  Real :: rRead
  Type :: stPLink
    Real :: rValue
    Type(stPLink) , Pointer :: pNext
  End Type stPLink
  Type( stPLink ) , Target :: stFirst
  Type( stPLink ) , Pointer :: pLocal
  pLocal => stFirst
  iCount = 0
  rRead = 1.0
  write(*,*) '请输入一些数,输入0结束:'
  Do while ( .True. )
    Read(*,*) rRead
    If ( rRead < 0.0001 ) then
      Exit
    End If
    pLocal%rValue = rRead
    Allocate( pLocal%pNext ) 
    pLocal => pLocal%pNext
    iCount = iCount + 1
  End Do
  pLocal => stFirst
  Do i = 1 , iCount
    Write(*,*) pLocal%rValue
    pLocal => pLocal%pNext
  End Do
End Program Main

4 楼


谢谢雪球,说的很详细,最后一个输出循环我测试了下可以做如下改动:

  pLocal => stLocal
  Do i = 1 , iCount
    Write(*,*) pLocal%rValue
    pLocal => pLocal%pNext
  End Do
改成:
  Do i = 1 ,iCount
    Write(*,*) stLocal%rValue
    stLocal =stLocal%pNext
  End Do
[em1]

5 楼

我先写的 stLocal 后来觉得写成 stFirst 更确切。

所以把帖子稍微改了一下。

之所以我不像你那样写。是因为我想保持 stFirst 不变,以供将来操作。

通常来说,First 都不要变,否则以后找不到“线头”了

6 楼


恩有道理,我那样写的话最后stlocal就指向了链表的最后没有东西了

我来回复

您尚未登录,请登录后再回复。点此登录或注册