Fortran Coder

楼主: btx97
打印 上一主题 下一主题

[指针] 关于fortran里指针的讨论

[复制链接]

712

帖子

4

主题

0

精华

大师

农村外出务工人员

F 币
607 元
贡献
311 点

新人勋章爱心勋章水王勋章元老勋章热心勋章

楼主
发表于 2014-2-20 09:49:48 | 显示全部楼层
Fortran 的指针具有特殊性。一般来说,所占的内存比它的Target要少很多很多。

if 指向单变量或结构体 then
  在32位编译器里,Fortran指针仅占 4 字节。通常叫 address
else 指向数组或结构体指针 then
  不同编译器会不同。它们会定义一个结构体来描述指向的数组。老外叫 descriptor
endif

单变量就不说了,与 C 的指针是一样的。C++如果不特别处理,指针也是4字节,仅仅表示目标的地址。
指向数组的话,descriptor 大概会是类似这样一个结构体:
Type Pointer_descriptor
  integer Pointer_address !// 这个是与 address 等效的
  integer Array_Dimension !// 数组的维度
  integer Array_Size_Element !// 数组每个元素的大小
  integer ArrayUBound( Array_Dimension ) , ArrayDBound( Array_Dimension ) !// 每个维度的上下限
End Type Pointer_descriptor

这个结构体在源代码中并不存在,Intel Fortran 会采用类似这样的结构来描述一个指向数组的指针。其他编译器会有类似的描述,但不完全相同。

由此可知,指向数组的指针所占的内存,通常在几十字节。如果你指向一个 a(2,2) 的数组,那么指针所占的内存反而比数组本身还大。如果你指向一个 a(100,100) 的数组,那么指针所占的内存就比数组小得多了。

Fortran 的指针,会比 C 的指针占的内存要大一些。

指针交换数组,通常也会比数组直接交换要高效。(注意是通常,上面的可作为反例)
这可以从生活中得到一些类比:

假设两家人,王家住在XX街18号,李家住在XX街9号。现在两家要搬家,各自搬到对方家。(交换房屋)
数组交换就好比:王家把家具床柜子桌子凳子日用品全部搬到临时住处,然后李家把家具床柜子桌子凳子日用品全部搬到王家,最后王家再从临时住处搬到李家。
而指针交换就好比:把18号门牌挂到临时住处,把9号门牌挂到原18号,最后把18号门牌挂到原9号。

显然,指针交换更高效。

Fortran 的指针与 C 的指针差别就是,C 的指针只有地址(门牌号),Fortran 的指针除了地址,还有数组的一些参数,如维度,单元素的大小,各维度上下限(可以类比王家李家的电费余额,水表底数)。

712

帖子

4

主题

0

精华

大师

农村外出务工人员

F 币
607 元
贡献
311 点

新人勋章爱心勋章水王勋章元老勋章热心勋章

沙发
发表于 2014-2-21 10:29:51 | 显示全部楼层
delta 发表于 2014-2-21 10:08
膜拜各位大虾

Fortran还不支持指针数组,不然在数值计算中也可以经常用用的 ...

有一个像是“耍赖皮”的方法使用指针数组。

[Fortran] 纯文本查看 复制代码
type pST_Array
  real , pointer :: p( : )
end type pST_Array
Type ( pST_Array) , pointer :: pA( : )
integer :: i , j
Allocate( pA( 10 ) ) !// 产生10个指向数组的指针。
Do i = 1 , 10
  Allocate( pA(i)%p(2) ) !// 每个指针指向一个2元素数组
  Do j = 1 , 2
    pA(i)%p(j) = i*100+j
  End Do
End Do
Do i = 1 , 10
  write( * , * ) pA(i)%p( : )
End Do  
!// 尚未书写释放指针代码
End Program

712

帖子

4

主题

0

精华

大师

农村外出务工人员

F 币
607 元
贡献
311 点

新人勋章爱心勋章水王勋章元老勋章热心勋章

板凳
发表于 2014-2-21 10:34:00 | 显示全部楼层
这里写 Fortran 代码有个 bug

p(:) 会被替换成表情。得写成 p( : )

712

帖子

4

主题

0

精华

大师

农村外出务工人员

F 币
607 元
贡献
311 点

新人勋章爱心勋章水王勋章元老勋章热心勋章

地板
发表于 2014-2-21 17:30:42 | 显示全部楼层
本帖最后由 chuxf 于 2014-2-21 17:36 编辑
btx97 发表于 2014-2-21 16:33
c 语言有指针数组和数组指针的区别,但fotran里好像没有这样的区别吧。

我的例子程序中p1指向了一个数组 ...

Fortran 里只有数组指针,指针数组可以像 8 楼的代码那样。

你的程序里 p1 是数组指针。p1 是指针,不是数组,只不过它指向的目标是数组。

p1(i,j) 可以取出对应的变量值,但 p1 依然是指针,不是数组。

关于指针 p+1 ,实现是非常容易的。只是地址加上每元素占用的字节数既可。但是 Fortran 语法不允许,目的是防止指针指向数组范围之外。

Fortran 指向数组的指针(数组指针),不单单是数组的首地址,而且包含数组的维度和上下限,因此,更可有效防范指针指向数组范围之外。

从编译器实现上看,Fortran的指针是受约束的,实现起来更难(换句话说,写一个支持指针的 Fortran 编译器,比写一个支持指针的 C 编译器难得多)。受约束会影响灵活性,但可增加数据安全。

这就好像 Discuz 论坛(咱们论坛使用的程序)一样,它使用了大量的代码来限制普通会员的 HTML 使用,比如会员发帖时输入 <iframe src="某恶意网址">,论坛程序会对这段代码进行改动,使得它并不会被浏览器当做插入页面来解释,所以在论坛发帖的时候你做不出漂亮的网页效果。但是,对论坛来说更安全。

最后,指向普通变量的指针,不能直接指向一个数组,但可以指向数组的某个元素,或者 type 派生类型的某一个普通变量成员。

[Fortran] 纯文本查看 复制代码
real ,pointer :: p
real , target :: a( 10 )
integer :: i
Do i = 1 , 10
 p => a(i)
End Do




您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

捐赠本站|Archiver|关于我们 About Us|小黑屋|Fcode ( 京ICP备18005632-2号 )

GMT+8, 2024-5-6 17:16

Powered by Tencent X3.4

© 2013-2024 Tencent

快速回复 返回顶部 返回列表