Fortran的数组与指针

##个人理解,欢迎指正##

  • 指针就是记录数据的内存地址的变量。指针可以指向单个变量,也可以指向数组。
  • 数组是一个概念,是若干个类型相同的元素的有序集合。

在Fortran中,数组中存放的元素可以是整数,实数,复数,甚至结构体(又称“自定义数据类型”),但不能是指针 即,不存在这样一个数组,该数组的每一个元素都是一个指针,分别指向不同的数组。

那么怎样才能实现这样一个数组,其中的每一个元素都能指向其他的数组呢?

 

实现一个数组,其中的元素指向不同的数组

因为数组中存放的元素可以是结构体,那么可以通过定义一个结构体,在结构体中定义一个指针变量来解决。

type container
  class(object), pointer :: obj
end type container

type(container), allocatable, dimension(:) :: objects
allocate (objects(0:num_objects))
objects(0)%obj => s1

其中,objects(0:num_objects)就是定义的结构体数组,数组中的第0个元素的obj分量(objects(0)%obj)指向一个变量s1,s1是类型为object的变量。

上式objects数组中的每一个元素都是指向单个变量的,那么如果需要结构体数组中的每一个元素都指向一个数组,则定义结构体中的指针变量需要定义为是指向数组的(下面第10行):

 1 program ex1
 2 implicit none
 3 integer :: i,j
 4 
 5 !//声明目标数组work
 6 real(RK),allocatable,target :: work(:,:)
 7 
 8 !//定义结构体类型qcontainer,该类型中的分量obj可以指向一个一维的数组
 9 type qcontainer
10         real(RK),pointer :: obj(:)
11 end type qcontainer    
12 
13 !//声明一个一维的的数组qtwork
14 type(qcontainer),allocatable :: qtwork(:) 
15 
16 !//定义数组work并赋初值
17 allocate(work(2,3))
18 do i=1,2
19     do j=1,3
20         work(i,j)=i*j**2*7
21     end do
22 end do
23 
24 !//定义数组qtwork
25 allocate(qtwork(3))
26 
27 !//qtwork中第j个元素的object分量指向数组work的第j列
28 qtwork(j)%obj => work(:,j)
29 
30 
31 end program ex1

 

关于彭书中的“”指针数组“

彭国伦《Fortran95程序设计》书中275页上说,“指针也可以声明成数组”,并给了以下示例代码

 1 program ex1004
 2   implicit none
 3   integer, pointer :: a(:)
 4   integer, target  :: b(5)=(/ 1,2,3,4,5 /)
 5   ! 把指针数组a指向数组b
 6   a=>b  
 7   ! a(15)=>b(15)
 8   write(*,*) a
 9   a=>b(1:3)
10   ! a(1)=>b(1), a(2)=>b(2), a(3)=>b(3)
11   write(*,*) a 
12   a=>b(1:5:2)
13   ! a(1)=>b(1), a(2)=>b(3), a(3)=>b(5)
14   write(*,*) a 
15   a=>b(5:1:-1)
16   ! a(1)=>b(5), a(2)=>b(4), a(3)=>b(3), a(4)=>b(2), a(5)=>b(1)
17   write(*,*) a 
18   stop
19 end

这里用指针a表示了数组b。这告诉我们,指针不仅可以指向单个变量的内存地址,还可以指向数组。

但是需要注意的是,指针a(:)中的每一个变量a(i)都确定的表示某一个单独的变量,而不是表示变量的集合(数组)即指针a(:)只能表示一个数组,不能同时表示多个数组的集合。

另外,需要注意,声明指针a的时候,可以说明a的形状,但不能指定a的数组大小。换句话说,声明指针a的时候,可以告诉编译器,a指向的是几维的数组,但是不能告诉编译器,a指向的数组是大小是100×100的。

所以,如果第3行换成以下语句是非法的

!//非法的代码
 integer, pointer :: a(5)

编译器错误提示是“ ALLOCATABLE or POINTER attribute dictates a deferred-shape-array.” 即声明变量时,allocatable或pointer的属性表明数组为假定形状数组。如果此时声明上述语句(即给了数组的大小),那显然矛盾。

 

总结

  • 在Fortran中,指针可以指向一个数组或者一个数组中的一部分,但指针不能同时表示多个数组。
  • 数组是若干相同类型元素的集合,但数组的元素不能是指针。
  • 如果想实现一个数组,且数组的元素具有指针的功能,可以定义一个结构体类型的数组。

 

附录代码:

 

 1 program test
 2     implicit none
 3     integer i,j,k
 4     real,allocatable,target :: work(:,:)
 5 
 6     type qcontainer
 7         real,pointer :: obj(:)
 8     end type qcontainer
 9 
10     type(qcontainer),allocatable :: qtwork(:) ,qtemp
11 
12 
13     allocate(work(2,3))
14     allocate(qtwork(3))
15 
16     !//初始化
17     do j=1,3
18         do i=1,2
19             work(i,j)=i*j**2*7
20         end do
21     end do
22 
23     !//指针变量赋值
24     do j=1,3
25         qtwork(j)%obj => work(:,j)
26     end do
27 
28     !//打印输入数组
29     print*,"input array: "
30     do j=1,3
31         print*,work(:,j)
32     end do
33 
34     !//打印指向的数组
35     print*,"point array: "
36     do j=1,3
37         print*,qtwork(j)%obj
38     end do
39 
40     !//置换
41     print*,"swap"
42     qtemp = qtwork(1)
43     do j=1,2
44         qtwork(j) = qtwork(j+1)
45     end do
46     qtwork(3)=qtemp
47 
48     !//输出置换结果
49     do j=1,3
50         print*,qtwork(j)%obj
51     end do
52 
53     deallocate(work)
54 
55 
56     end program

 

输出结果:

 

 input array:
   7.000000       14.00000
   28.00000       56.00000
   63.00000       126.0000
 point array:
   7.000000       14.00000
   28.00000       56.00000
   63.00000       126.0000
 swap
   28.00000       56.00000
   63.00000       126.0000
   7.000000       14.00000
Press any key to continue . . .

 

posted @ 2019-03-11 17:19  chinagod  阅读(4789)  评论(0编辑  收藏  举报