使用 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*4
或 real*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 强制显式变量声明的主要内容,如果未能解决你的问题,请参考以下文章