【问题标题】:Fortran 77 function return type mismatch [duplicate]Fortran 77函数返回类型不匹配[重复]
【发布时间】:2019-10-25 17:24:15
【问题描述】:

我一直在尝试为大学项目学习 Fortran 77,我在 Windows 10 中编写了以下代码:

program Q_Value
real BEs(4),Masses(4)
real Q,Tthr
integer i,Nuclei(4,2),A,Z

do 10 i=1,4,1
        write(*,100)'Give the info for Nuclei:',i
 100        format(A,I1)
        write(*,*)'A='
        read(*,*)Nuclei(i,1)
        write(*,*)'Z='
        read(*,*)Nuclei(i,2)
        if((Nuclei(i,1).EQ.0).OR.(Nuclei(i,2).EQ.0))then
            BEs(i)=0.
        else
            BEs(i)=BetheWeiss(Nuclei(i,1),Nuclei(i,2))
        endif
        Masses(i)=Mass(Nuclei(i,1),Nuclei(i,2),BEs(i))
 10 continue

[...]
end
real function Mass(A,Z,BE)
    integer A,Z
    real BE,mass
c   local var's
    parameter(Mp=938.2720813,Mn=939.5654133)
c   statements
    Mass=((A-Z)*Mn)+(Z*Mp)-BE
    return 
    end

在 GNU Fortran (gfortran 8.1.0) 中编译时出现以下错误:

Masses(i)=Mass(Nuclei(i,1),Nuclei(i,2),BEs(i))
                     1
Error: Return type mismatch of function 'mass' at (1) (INTEGER(4)/REAL(4))

谁能帮我解决这个问题,因为就我而言,我的函数返回一个实数,Masses(i) 是一个实变量。

【问题讨论】:

  • 我想知道编译器是否正在处理函数内方程的整数元素的某种类型解析,例如'integer A,Z'以及它们在返回语句之前参与质量计算.也许 gnu fortran 有更严格的类型规则?
  • 感谢您的回复@David W。我尝试在最后一个公式中用 dble 转换 A 和 Z(质量=....),但不幸的是没有任何改变。
  • 好吧,我必须承认我的 fortran 已经过时了,但是如果你将 typedef 从函数中取出并确保返回类型的声明匹配 - 并且两者都指定了相同的大小写
  • 你不想写implicit integer (A-Z) 而不是integer A,Z 吗?但即使是,您真正想要的是所有程序单元(主程序、函数、子程序)中的implicit none。另外,强烈考虑本世纪的某些版本的 Fortran。请检查您是否准确复制了源代码。请将其设为minimal reproducible example,我们可以在没有任何[...] 的情况下自行编译。
  • @Theodepastas 我终于找到了解决方案。发表了答案;在在线编译器上试了一下。

标签: function fortran gfortran type-mismatch


【解决方案1】:

默认的隐式类型规则是,如果名称的第一个字母是 I 、 J 、 K 、 L 、 M 或 N ,则数据类型为整数,否则为实数。

因为你的函数是mass(),它以M开头并且没有在主程序中声明,所以它被认为是一个整数函数。这与函数声明冲突,编译器会抱怨。如果您想保留极其古老的 FORTRAN 77,您需要的是

real mass

在主程序中。

最好使用现代 Fortran 的功能,从IMPLICIT NONE 开始,将函数放入模块中或使其内部到主程序中。

您也可以在主程序中使用替代的隐式语句来修复错误消息(请参阅我的评论),但我强烈不鼓励除IMPLICIT NONE 之外的任何其他内容。

【讨论】:

    【解决方案2】:

    函数 Mass 是在主程序范围之外声明的。因此,即使在同一源代码块中明确声明了 Mass 函数,编译器也会推断出该函数的类型。为了克服这个问题,你需要在调用程序中声明一个接口块:

    program Q_Value
    [...]
    interface Mass
      real function Mass(A,Z,BE)
      integer :: A
      integer :: Z 
      real :: BE
      end function
      end interface 
    
    end program
    
    real function Mass(A, Z, BE)
    [..]
    end function
    

    我在https://onlinegdb.com/BkjLxcy9S 有一个使用此解决方案的原始源代码的有效修改版本。我删除了对 BetheWeiss 的调用并将其替换为任意赋值,推断它只是您在原始帖子中省略的源代码中定义的函数。那里也需要相同类型的界面。

    【讨论】:

    • 请注意,它与 Fortran 77 不兼容,但它是解决此问题的 Fortran 90 技术之一。这种技术非常适合一次性连接旧式功能,但模块通常更容易学习。当然,接口并不是在现代 Fortran 中编写大型程序的通用工具。在这种特定情况下,在函数之前使用 contains 并在函数之后使用 end program 也会更快(正如我在答案中所说 - 将函数设为内部)。同样,模块通常要好得多。不要小看implicit none的重要性。
    • 没有建议这是一个广泛或通用的解决方案;只是达到解决编译问题目的的一种手段。我敢肯定,任何涉及使用这种老式语言的项目都会出现许多其他问题。
    猜你喜欢
    • 2014-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多