主题:[讨论]请问fortran指针何时能够指向地址啊???
bactone
[专家分:0] 发布于 2012-06-12 19:32:00
请问大家fortran指针何时能够指向地址啊???
现在的版本好像只是给所指对象取了一个别名,还有在fortran中能否像C++一样取出一个变量的地址赋给一个指针变量?
回复列表 (共6个回复)
沙发
臭石头雪球 [专家分:23030] 发布于 2012-06-12 20:24:00
指向地址?你是说指向指针的指针?
现在可不止是取个别名。跟C++一样是存储的变量的地址哦亲。只不过使用的时候有一些限制而已。
板凳
bactone [专家分:0] 发布于 2012-06-12 21:04:00
啊啊啊,请大侠赐教啊,能够详细一点回答在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 楼
臭石头雪球 [专家分:23030] 发布于 2012-06-12 21:41:00
第一个问题:
其实 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 楼
bactone [专家分:0] 发布于 2012-06-12 22:09:00
谢谢雪球,说的很详细,最后一个输出循环我测试了下可以做如下改动:
将
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 楼
臭石头雪球 [专家分:23030] 发布于 2012-06-12 22:25:00
我先写的 stLocal 后来觉得写成 stFirst 更确切。
所以把帖子稍微改了一下。
之所以我不像你那样写。是因为我想保持 stFirst 不变,以供将来操作。
通常来说,First 都不要变,否则以后找不到“线头”了
6 楼
bactone [专家分:0] 发布于 2012-06-13 12:48:00
恩有道理,我那样写的话最后stlocal就指向了链表的最后没有东西了
我来回复