Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pointers 将空指针实际参数传递给派生类型的成员过程_Pointers_Fortran_Gfortran_Intel Fortran - Fatal编程技术网

Pointers 将空指针实际参数传递给派生类型的成员过程

Pointers 将空指针实际参数传递给派生类型的成员过程,pointers,fortran,gfortran,intel-fortran,Pointers,Fortran,Gfortran,Intel Fortran,将空指针传递给函数和子例程是否有效 符合Fortran 2003标准吗?请假设调用的函数和 子例程可以正确处理伪参数为 空指针。我特别感兴趣的是这种功能和 子例程是“成员”函数和派生类型的子例程 我希望避免检查中每个指针的关联状态 呼叫方,如果标准允许,与我不允许的方式大致相同 必须单独处理零大小数组。同时,我不想 依赖于标准未规定的行为 就我在下面的示例中所做的尝试而言,ifort和gfortran显示 在这一点上有不同的行为 moo.f90 MODULE moo IMPLICIT NON

将空指针传递给函数和子例程是否有效 符合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
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
main.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
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
的行为是否优雅?或者,标准没有 你对这一点有什么看法吗

我注意到这两个编译器都是较旧的版本,我猜
较新的版本可能会显示不同的行为

这两个编译器在这里的行为都是合法的。也就是说,代码有错误,但不需要编译器提供诊断

请看指针赋值语句

pLL_d => pLL_s%func1()
这是对类型为
LL
的绑定名称
func1
的引用。但是,在此处执行到达的点处,pLL\u s不关联。因此,不允许使用程序参考。根据Fortran 2008 12.5.1:

程序指示符中的数据参考不应。。。没有关联的指针

由于这不是编号约束,因此程序员有责任确保遵从性

从这个问题转到一般问题“是否向函数和子例程传递空指针是有效的?”,答案是“是的,只要它的使用不违反通常的条件”

总之,虽然在概念上

pLL_d => pLL_s%func1()   ! Using func1 as a binding name
在中国是这样的吗

pLL_d => func1(pLL_s)    ! For the module's procedure func1
问题不在于
pLL\u s
是一个不关联的指针实际参数。后一种形式是允许的,但前一种形式是不允许的


对这个问题感兴趣的是关于函数结果定义的要求。对于
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
与指针虚拟对象对应的潜在非关联实际值。传递的对象伪参数实际上只是一个非常特殊的情况。

非常感谢您的回答。我仍然很难理解编译器是如何解释代码的。在回答的前几段中,您对
pLL\u d=>pLL\u s%func1()
的解释是指
pLL\u d
被视为一个过程指针,这一行代码意味着
pLL\u d
指向函数
func1
(属于
LL
类型的特定对象)?如果您能提供更多帮助,我将不胜感激。
pLL\u d
被声明为数据指针,永远不能被视为过程指针。因此,在指针赋值语句
pLL\u d
上,获取函数引用
func1(pLL\u s)
结果的指针关联状态。对于函数
f
,则
f()
表示函数的结果,而
f
是函数本身,因此
ptr=>f
不同于
ptr=>f()
。但是,对于像
pLL\u s%func1
这样的类型绑定,不能将其视为过程(参见示例)。这是一个非常有趣和困难的领域。有些语言有classmethods,您只需使用
键入\u name%method()
即可调用它们。我现在不确定的是,您引用的限制是否也适用于没有传递参数的类型绑定过程,但可能适用(我没有检查标准)。@VladimirF,您的意思是引用
pLL_s%func1()当
func1
具有
nopass
pLL\u
没有关联时,允许使用
?是的,这类事情。