【问题标题】:Why is interface required here for correct results [duplicate]为什么此处需要接口才能获得正确的结果[重复]
【发布时间】:2020-09-26 10:32:50
【问题描述】:

考虑代码:

subroutine func(i) bind(c)
  use, intrinsic :: ISO_C_BINDING, only: c_float
  implicit none
  real(c_float), value :: i
  print *, i, "+", i, "=", i + i
end subroutine

program main
  use, intrinsic :: ISO_C_BINDING, only: c_float
  implicit none
  real(c_float) :: i = 1.0
  call func(i)
end program

它显示5.61379690E-30 + 5.61379690E-30 = 1.12275938E-29,这当然是错误的。仅当我添加显式接口时,它才会输出正确的结果:

subroutine func(i) bind(c)
  use, intrinsic :: ISO_C_BINDING, only: c_float
  implicit none
  real(c_float), value :: i
  print *, i, "+", i, "=", i + i
end subroutine

program main
  implicit none
  interface
    subroutine func(i)
      real, value :: i
    end subroutine func
  end interface
  real :: i = 1.0
  call func(i)
end program

然后我得到1.00000000 + 1.00000000 = 2.00000000,这是正确的。

但是是什么导致了这里的错误?为什么需要一个不添加任何新信息的额外界面?

我使用 gfortran,GCC,版本 7.4.0

【问题讨论】:

    标签: floating-point fortran ieee-754


    【解决方案1】:

    每个具有value 虚拟参数的函数或子例程都需要一个显式接口。这同样适用于具有bind() 属性的过程。否则调用代码不知道如何正确调用。

    Fortran 2018 草案指出:

    15.4.2.2 显式接口
    1 在过程标识符的范围内,如果该过程是 不是语句函数和
    ...
    (3) 程序有一个 (a) 具有 ALLOCATABLE、ASYNCHRONOUS、OPTIONAL、 POINTER、TARGET、VALUE 或 VOLATILE 属性,...
    ...
    (6) 程序有BIND属性。

    请注意,explicit interface 与您使用的 interface 块不同。接口块是提供显式接口的可能方式之一。更好的选择通常是使用模块,有时使用内部过程。

    标准将显式接口定义为:

    3.90.2
    显式接口
    过程的接口,包括过程的所有特征及其虚拟参数的名称 除了星号虚拟参数 (15.4.2)

    这与interface 块不同,它是一段以interface 关键字开头的实际代码。

    【讨论】:

    • 好的,很高兴知道,谢谢。但是为什么接口不是显式的?我从thistutorial (section interface blocks) 中得到了语法,它把它称为“显式”(但没有提到它是值参数所必需的,只有可选的、关键字、指针等)......怎么能我更改了问题中的界面,使其真正明确和正确?
    • @user3137490 您在第二个示例中的接口块确实提供了显式接口。在您的第一个代码示例中,函数是外部的,因此接口是隐式的。
    • 只要把所有的子程序和函数都粘在模块里,就不用担心这个了,还能获得其他好处。
    猜你喜欢
    • 1970-01-01
    • 2011-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多