使用 gfortran 强制显式变量声明

Posted

技术标签:

【中文标题】使用 gfortran 强制显式变量声明【英文标题】:Force explicit variable declaration with gfortran 【发布时间】:2010-08-24 18:47:40 【问题描述】:

我正在使用 mex 从 matlab 链接一些 fortran 代码 (f90),我偶尔会遇到 matlab 冻结。

过去,由于数据类型(比如整数*4 与整数*8)不匹配,我会发生冻结。

我正在链接的代码有很多隐式定义的变量,所以我想知道是否存在仅偶尔发生的隐藏数据类型冲突。

为了排除数据类型不匹配是导致冻结的原因,我希望编译器要求所有变量都被显式声明。

问题:

    如何让 gfortran 要求在编译时显式声明所有变量?如果做不到这一点,有没有办法至少得到警告?

    gfortran 是否将“真实”数据类型解释为所有体系结构中的特定类型?如果有,是哪一个(real*4, real*8, ...)?

    是否强制 gfortran 将“真实”数据类型解释为特定类型,例如“真实*4”?

    关于从 matlab 中的 mex 编译例程调用时导致 fortran 代码冻结的原因有什么想法(数据类型不匹配除外)?

感谢您的帮助。

在我弄清楚这一点之前,我将通过许多行代码尝试列出所有隐式定义的变量。 不用说,我将非常感谢任何让我从如此无聊的任务中解脱出来的人......

最好的,

G.

【问题讨论】:

【参考方案1】:

如前所述,在您的源代码中,您可以使用implicit none。优点是它可以移植到所有编译器。

使用 gfortran,您可以使用编译器选项 -fimplicit-none。这个优点是即使您忘记包含隐式无,这也会捕获您忘记显式键入的变量。大多数其他编译器都有类似的选项。

强烈推荐两者 - 隐式类型是有害的,并且允许错误创建意外变量的拼写错误。

简单的“真实”意味着什么取决于编译器——如果您有特定的要求,最好使用更具体的声明。最好的方法是用选定的真实类型内在函数定义一个参数并使用它——类似的讨论见Fortran: integer*4 vs integer(4) vs integer(kind=4)

【讨论】:

非常感谢,特别是关于 -fimplicit-none 标志的提示【参考方案2】:

IMPLICIT NONE 和编译器选项已经提到。

我们来谈谈浮点运算。问题是(ss 提到here)MATLAB 根据IEEE® Standard 754 构造双精度(或双精度)和单精度(或单精度)数据类型,但 Fortran 标准不需要它的默认值和双精度真正的符合这个标准。如您所见,标准文档甚至使用其他名称(默认为实数,不是单精度)。

MODULE kinds

  IMPLICIT NONE

  INTEGER, PARAMETER :: fortran_default = kind(0.0)
  INTEGER, PARAMETER :: fortran_double = kind(0.0D0)
  INTEGER, PARAMETER :: ieee_single = selected_real_kind(7, 38)
  INTEGER, PARAMETER :: ieee_double = selected_real_kind(15, 307)

END MODULE kinds

在我的种类规范的前两个字符串中,我使用了方便的方法来获取默认实数和双精度实数的种类。接下来的两种对应于提到的 IEEE 标准。

PROGRAM main

  USE kinds

  IMPLICIT NONE

  REAL(kind=ieee_single) :: is
  REAL(kind=ieee_double) :: id
  REAL(kind=fortran_default) :: fs
  REAL(kind=fortran_double) :: fd

  PRINT *, kind(is), precision(is), range(is)
  PRINT *, kind(id), precision(id), range(id)
  PRINT *, kind(fs), precision(fs), range(fs)
  PRINT *, kind(fd), precision(fd), range(fd)

END PROGRAM main 

我的机器(Mac OS X 10.6,gfortran 4.5.1)上的输出是:

   8          15         307
   8          15         307
   4           6          37
   8          15         307

所以 Fortran 默认的实数类型不等于 IEEE 标准的单精度浮点数类型。

所以它可能是错误的来源。精度在某处丢失,某个变量变为等于 0.0,而不是稍微大于/小于 0.0,然后除以该值(恰好是 0.0)。嗯,它可以冻结程序。

【讨论】:

观察 >> 推测 - 非常好。 Technically selected_real_kind(7, 38) 提供至少 7 位精度——如果编译器选择它可以提供更多,因此不能保证选择 IEEE 类型。如果您绝对必须拥有 IEEE 类型,那么 Fortran 2003 有新的 IEEE 模块——但目前还没有得到普遍支持。 @M.S.B.:您的评论完全有效。这个想法是在 Fortran 代码中具有至少与 IEEE 单精度和双精度一样精度的浮点数。【参考方案3】:
    您可以通过添加implicit none 来要求所有变量都显式声明。 我相信默认的“真实”数据类型是real*4。 您可以使用命令行标志-fdefault-real-8 强制将所有声明为real 的变量解释为real*8

注意(为了写更多的代码,不一定要解决当前的bug): 如果您使用 Fortran 90 代码,则可以将 real(kind=4)real(kind=8) 与 gfortran 一起使用,而不是 real*4real*8 语法。我已经不再使用命令行标志设置实数或整数大小,而是使用integer, parameter :: REAL_SIZE 变量来保存适当的数字(我通常选择 4 或 8,因为我使用的所有编译器都支持它们,但如果你想要非常便携,你应该使用selected_real_kind 例程)

【讨论】:

非常感谢,特别是关于 -fdefault-real-8 标志的提示。你知道是否还有 -fdefault-real-4 标志吗?我在 gfortran 上尝试过,但似乎没有用... 我不这么认为,因为那只是默认设置。 那么真实的默认值不依赖于架构吗? 没有。它依赖于架构。并注意 real kind /= 存储值的字节数!【参考方案4】:

其中一个适用于大多数编译器,因为 Fortran 77:

implicit none

implicit undefined(a-z)

Real 依赖于架构;默认大小通常可以通过命令行选项修改。

我没有任何与 Matlab 链接的经验。

【讨论】:

以上是关于使用 gfortran 强制显式变量声明的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 声明全局变量和局部变量

JS中声明全局变量

基于JavaScript 声明全局变量的三种方式详解

如果变量类型没有显式声明,为啥在以下情况下需要可选链接? [复制]

基于JavaScript 声明全局变量的三种方式详解

基于JavaScript 声明全局变量的三种方式详解