将空指针传递给函数并且子例程有效 到Fortran 2003标准?请假设被调用的函数和 子例程可以正确处理伪参数的情况 空指针。我对这种功能和情况特别感兴趣 子程序是一个'成员'派生类型的函数和子例程。
我想避免检查每个指针的关联状态 如果标准允许,则呼叫方,与我不同的方式相同 必须分别处理零大小的数组。与此同时,我不想 依赖于标准未规定的行为。
据我尝试使用以下示例,ifort
和gfortran
显示
关于这一点的不同行为。
moo.f90
MODULE moo
IMPLICIT NONE
PRIVATE
PUBLIC LL
TYPE LL
INTEGER :: i0
CONTAINS
PROCEDURE :: func1
PROCEDURE :: func2
END type LL
CONTAINS
FUNCTION func1(self) RESULT(pLL_dest)
TYPE(LL), POINTER :: pLL_dest
CLASS(LL), TARGET, INTENT(IN) :: self
write(*,*) 'hello from func1'
pLL_dest => null()
!pLL_dest => self
END FUNCTION func1
FUNCTION func2(self) RESULT(flg)
LOGICAL :: flg
CLASS(LL), TARGET, INTENT(IN) :: self
write(*,*) 'hello from func2'
flg = .true.
END FUNCTION func2
END MODULE moo
main.f90
PROGRAM chk_nullpo
USE moo, ONLY : LL
IMPLICIT NONE
!CLASS(LL), POINTER :: pLL_s=>null()
TYPE(LL), POINTER :: pLL_s=>null()
TYPE(LL), POINTER :: pLL_d=>null()
LOGICAL :: flg
write(*,*) 'associated(pLL_s) =',associated(pLL_s)
write(*,*) 'associated(pLL_d) =',associated(pLL_d)
write(*,*) 'func1..'
pLL_d => pLL_s%func1()
write(*,*) 'associated(pLL_s) =',associated(pLL_s)
write(*,*) 'associated(pLL_d) =',associated(pLL_d)
write(*,*) 'func2..'
flg =pLL_s%func2()
write(*,*) 'flg=', flg
write(*,*) 'associated(pLL_s) =',associated(pLL_s)
write(*,*) 'associated(pLL_d) =',associated(pLL_d)
write(*,*) 'normal end'
END PROGRAM chk_nullpo
ifort
生成的可执行文件在成员时导致运行时错误
使用空指针调用子例程func2
。
$ ifort -v
ifort version 14.0.2
$ ifort -c moo.f90 -stand f03 -warn all -check
$ ifort -c main.f90 -stand f03 -warn all -check
$ ifort -o ex_ifort moo.o main.o -stand f03 -warn all -check
ifort: warning #10182: disabling optimization; runtime debug checks enabled
$ ./ex_ifort
associated(pLL_s) = F
associated(pLL_d) = F
func1..
hello from func1
associated(pLL_s) = F
associated(pLL_d) = F
func2..
forrtl: severe (408): fort: (7): Attempt to use pointer PLL_S when it is not associated with a target
Image PC Routine Line Source
ex_ifort 0000000000402AE1 Unknown Unknown Unknown
ex_ifort 0000000000402336 Unknown Unknown Unknown
libc.so.6 00002AC53B23DF45 Unknown Unknown Unknown
ex_ifort 0000000000402229 Unknown Unknown Unknown
$
另一方面,gfortran
生成的可执行文件没有错误地完成。
$ gfortran --version
GNU Fortran (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
Copyright (C) 2013 Free Software Foundation, Inc.
GNU Fortran comes with NO WARRANTY, to the extent permitted by law.
You may redistribute copies of GNU Fortran
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING
$ gfortran -c moo.f90 -std=f2003 -Wall -fbounds-check
moo.f90:26.21:
FUNCTION func2(self) RESULT(flg)
1
Warning: Unused dummy argument 'self' at (1)
moo.f90:16.21:
FUNCTION func1(self) RESULT(pLL_dest)
1
Warning: Unused dummy argument 'self' at (1)
$ gfortran -c main.f90 -std=f2003 -Wall -fbounds-check
$ gfortran -o ex_gfortran moo.o main.o -std=f2003 -Wall -fbounds-check
$ ./ex_gfortran
associated(pLL_s) = F
associated(pLL_d) = F
func1..
hello from func1
associated(pLL_s) = F
associated(pLL_d) = F
func2..
hello from func2
flg= T
associated(pLL_s) = F
associated(pLL_d) = F
normal end
$
ifort
的行为是否符合标准,或
gfortran
只是优雅的行为?或者,标准没有
对这一点说什么呢?
我注意到这两个编译器都是旧版本,我猜 较新的版本可能会显示不同的行为。
答案 0 :(得分:2)
这两个编译器在这里都以合法的方式运行。也就是说,代码有问题但不是需要编译器提供诊断的方式。
查看指针赋值语句
pLL_d => pLL_s%func1()
这是对func1
类型的绑定名LL
的引用。但是,在此处执行到达时pLL_s
没有关联。因此不允许使用过程参考。根据Fortran 2008 12.5.1:
procedure-designator 中的 data-ref 不应是......与之无关的指针。
由于这不是编号约束,程序员有责任确保合规。
继续将这个问题转移到一般问题"是将空指针传递给函数和子程序有效吗?",答案是"是的,只要它的使用不&# 39;违反通常的条件"。
总之,虽然在概念上是参考
pLL_d => pLL_s%func1() ! Using func1 as a binding name
就像
中的那样pLL_d => func1(pLL_s) ! For the module's procedure func1
问题不在于pLL_s
是一个没有关联的指针实际参数。后一种形式是允许的,但前者不是。 1
对这个问题感兴趣的是关于函数结果定义的要求。对于func1
,函数结果是指针,因此必须定义结果的关联状态。如果函数由其绑定名称引用,则必须定义self
的关联状态。实际上,self
是关联的。
1 这实际上有点过于简单化了。虽然可以允许一个过程是一个非关联指针的实际参数,但这并不适用于这些过程。
查看伪参数的声明
CLASS(LL), TARGET, INTENT(IN) :: self
这里self
是一个非可选的非指针虚拟对象。要成为与指针实际参数相关联的参数,实际参数必须与指针相关联。因此,函数不是正确处理伪参数为空指针的情况的函数"。
那就是说,像
这样的陈述没有错pLL_d => pLL_s%func1(ptr) ! or
pLL_d => func1(pLL_s, ptr)
与pLL_s
指针关联,ptr
与指针虚拟对应的潜在非关联实际。传递对象伪参数实际上只是一个非常特殊的情况。