【问题标题】:Intel Fortran says actual argument doesn't match dummy argument?英特尔 Fortran 说实际参数与虚拟参数不匹配?
【发布时间】:2014-04-26 10:27:54
【问题描述】:

对于这个看似非常基本的问题,请提前道歉。不幸的是,我不是 Fortran 程序员,但我不得不维护一些遗留的 FORTRAN77 代码,而且它不能在 Intel Visual Fortran Parallel XE 2013(带有 VS2010)中编译。

我得到的错误是

错误 #6633:实际参数的类型与虚拟参数的类型不同。

它发生在对项目中定义的子例程的多次调用中。这段代码有语句

IMPLICIT REAL(8) (A-H,O-Z)

在整个调用函数和被调用的子例程中。 (原来是REAL*8,但我改了。)

这是否意味着所有名称都在 (A-H,O-Z) 范围内的参数都是两字节实数?我不知道它们在哪里被声明或以其他方式转换为任何其他类型。在子例程中调用的唯一函数是内在数学函数,例如 cos、sin、atan2。

这是一个例子:

INCLUDE 'common.f'
... ! (many lines of code)

C    Transform from RS to RL
    call RS$RL(0,iobl,1,vrel,xlatgc,gam,az,vph,vth,vr,
 *                 xlatgd,gaml,azl,vphl,vthl,vrl)

哪个调用

      SUBROUTINE RS$RL(ID,IOBL,IV,VREL,TH,GAM,AZ,VPH,VTH,VR,
 *                 THL,GAML,AZL,VPHL,VTHL,VRL)
C*  DECLARATIONS
      IMPLICIT REAL(8) (A-H,O-Z)
C     IMPLICIT REAL*8(A-H,O-Z)
      DEL = THL-TH
      IF(ID.EQ.0) THEN
C*  TRANSFORM FROM RS TO RL FRAME
        IF(IV.EQ.0) THEN
             VPH  = VREL*COS(GAM)*SIN(AZ)
             VTH  = VREL*COS(GAM)*COS(AZ)
             VR   = VREL*SIN(GAM)
        ENDIF
        IF(IOBL.EQ.0) THEN
             VPHL = VPH
             VTHL = VTH
             VRL  = VR
        ELSE
             VPHL = VPH
             VTHL = VTH*COS(DEL)-VR*SIN(DEL)
             VRL  = VTH*SIN(DEL)+VR*COS(DEL)
        ENDIF
        GAML = ATAN2(VRL,SQRT(VPHL**2+VTHL**2))
        AZL  = ATAN2(VPHL,VTHL)
      ELSE
C*  TRANSFORM FROM RL FRAME TO RS FRAME
        IF(IV.EQ.0) THEN
             VPHL = VREL*COS(GAML)*SIN(AZL)
             VTHL = VREL*COS(GAML)*COS(AZL)
             VRL  = VREL*SIN(GAML)
        ENDIF
        IF(IOBL.EQ.0) THEN
           VPH  = VPHL
           VTH  = VTHL
           VR   = VRL
        ELSE
           VPH  = VPHL
           VTH  = VTHL*COS(DEL)+VRL*SIN(DEL)
           VR   =-VTHL*SIN(DEL)+VRL*COS(DEL)
        ENDIF
        GAM  = ATAN2(VR,SQRT(VPH**2+VTH**2))
        AZ   = ATAN2(VPH,VTH)
      ENDIF
      RETURN
      END

common.f 文件在文件的最顶部包含IMPLICIT REAL(8) (A-H,O-Z) 行,随后是许多显式声明,其中没有一个包含导致编译错误的违规参数。

错误消息抱怨参数,vrel,xlatgc,gam,az。

【问题讨论】:

  • 显示具有 CALL 语句的范围的声明和/或规范部分(隐式语句)。如果调用范围缺少适当的 IMPLICIT 语句(或显式声明)来将实际参数的类型设置为 REAL(8),您将收到此错误。在没有 IMPLICIT 语句的情况下,以 A-H 和 O-Z 开头的变量默认为实数,通常不是 REAL(8)(命令行选项可以更改这一点)。 REAL(8) 和 REAL*8 之间的区别让人分心——它们是该编译器的同义词。
  • 我同意 IanH 的观点,但我也建议不要在你的标识符中使用 $,这是非常不标准的。另外,我会在任何地方都使用real*8,我认为在你的情况下引入“real(8)”是没有意义的。
  • @VladimirF - 是的,那些 $ 字符是一团糟。然而,它们出现在整个代码库中,所以我还没有经历过进行全局更改的乏味。对于我要保留的任何代码,我都会这样做。现在我只想能够编译这个烂摊子,看看它到底在做什么。
  • @IanH - 我编辑了 OP 以反映调用函数有一个 INCLUDE 语句,并且包含的​​文件中有 IMPLICIT 语句。我曾认为也许我也需要在调用函数中显式地使用 IMPLICIT 语句,但是当我尝试这样做时,我收到一个错误,说语句的顺序不正确。我没有USE 声明,所以我不确定这是为什么。

标签: types fortran intrinsics


【解决方案1】:

real(8)real*8 不同。第一个是不可移植的,在不同的编译器上可能意味着不同的东西。第二个是非标准的,但可以依赖于表示 8 字节实数。如果您切换回real*8,您会收到错误消息吗?错误消息是因为调用中的变量声明与子例程中的声明不一致。您显示调用但不显示这些变量的声明。这是需要比较的。

这里讨论了声明整数的方法:Fortran: integer*4 vs integer(4) vs integer(kind=4)。它与实数非常相似......我确信它也已经在stackoveflow的某个地方。

【讨论】:

  • 我将real*8 更改为real(8) 只是为了看看它是否有助于解决我的编译错误。我一直保留它,因为根据我读过的一些帖子,它似乎是首选。
  • real(8) 是错误的。使用某些编译器,它将为您提供 8 字节实数;与其他人一起被拒绝,您的程序将无法编译。
  • 我认为real*8 被认为是老式的,现在real(8)real(kind=8) 是首选。如果不是real(8),那么首选语法是什么?英特尔 Fortran 编译器似乎可以使用 real(8),顺便说一句。
  • real(N)real(kind=N) 是首选,但值 N 不能跨编译器移植。 Fortran 90 的最佳实践是使用 selected_real_kind 内在函数来确定 N。或者,现在您可以使用 use ISO_FORTRAN_ENVreal (real64)
  • REAL(8) 不是“错误的”,它只是不可移植 - 天壤之别。符号中的“$”符号也不可移植(也不符合标准),因此代码不会很快跳转到另一个处理器。
猜你喜欢
  • 1970-01-01
  • 2014-09-11
  • 1970-01-01
  • 2012-12-06
  • 1970-01-01
  • 2021-12-09
  • 1970-01-01
  • 1970-01-01
  • 2018-09-30
相关资源
最近更新 更多