1

Fortran 新手,我被要求使用 Salford/Silverfrost 编译器使用 Fortran 77 编写的旧 Fortran 代码库(最初的开发人员已去世)。

最初的开发人员COMMON广泛使用命名块(模拟全局变量,AFAIU),并且他EQUIVALENCE在需要时使用(重新)初始化块,如下面的代码片段:

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

      COMMON/COMMF2D/
     * ASCN(0:99,0:20,0:4)   
     *,FEMPTY2(8700)

      DIMENSION KLCKF2D(38400)
      EQUIVALENCE (KLCKF2D,ASCN)

      DO I= 1,38400                                              
      KLCKF2D(I)= 0
      END DO

这是一种可接受的编程实践还是只是一种黑客行为?另外,由于我正在尝试将代码移植到 GFortran,它是否可移植?(我知道像这样REAL*8的声明只是对编译器的提示,并不能保证)

4

2 回答 2

9

EQUIVALENCE什么都不,它当然不初始化任何东西,它EQUIVALENCE是一个定义或声明。这些天来(自从 Fortran 90 标准发布以来,力量一直在增长)EQUIVALENCE是一种黑客行为,应尽可能避免。

该语句声明 2 个变量共享存储(Fortran 标准称之为storage-association)。对此的一种解释是,等价的名称只是别名,但该语句的(ab-)使用允许程序员做一些其他事情,这些事情被 21 世纪的专业软件工程师认为是狡猾的。

例如,这适用于您发布的片段,EQUIVALENCE可用于让不同类型的变量共享相同的存储。您有一个名为ASCNwhich 的数组(隐式)REAL*8与一个名为 which 的数组KLCKF2D(再次隐式)等价于 type INTEGER。这意味着,如果您以一个名称引用存储,则位模式被解释为REALs,使用另一个名称它们是INTEGERs - 请注意,具有值的实数的位模式100.0不会(当然)被解释为整数100

黑客并不止于此。块声明的一个效果COMMON是将变量放在内存中,在您的情况下,10500 (= 100*21*5)元素ASCN后面是8700元素FEMPTY2。通过一点乘法和加法,您会发现38400 = 2*(10500+8700)与该程序中的默认整数大小一致,即 4 字节,即REAL*8其​​他变量中使用的 s 大小的一半。因此数组KLCKF2D大于ASCN但原始程序员知道下一个17400字节将被FEMPTY2.

所以是的,这可能是一种将程序内存数据部分中的所有位设置为 的方法0,但它(现在被认为是)一个可怕的黑客攻击。但它应该是可移植的——后续的 Fortran 标准对于从语言和编译器编写者中删除过时的特性非常保守,更重要的是,向后兼容性对 Fortran 程序员来说非常重要。

哦,为了回答你的问题,是COMMON的块是(注意过去时)声明和使用全局变量的 FORTRAN77 方式。MODULE如今,该语言提供了更安全的选择,即通过将变量包装在 a和 -关联它们来声明要全局共享的变量USE

看到这样的线我不会感到惊讶

COMMON/COMMF2D/KLCKF2D(38400)

在您的代码中,COMMON块也可以(ab-)用于重命名和重新键入存储位置。

虽然我正在对您的旧代码进行踢脚,但这些天隐式键入也令人不悦,显式键入所有声明要好得多。

于 2012-08-08T15:21:27.603 回答
0

好吧,不管是否便携,这种做法是……很常见的。(地球幽默。兽人。兽人。)我给你举个例子:我已经翻新过的游戏 Zork 的源代码中的数据——它实际上只是常见的块和等价物。https://github.com/LydiaMarieWilliamson/zork-fortran

在相邻的 C 翻译中,您将看到它在 C 中的表现。f2c 翻译器难以处理等价和​​公共块(正如您将在我的翻译日志中看到的那样)。我的建议是将其全部重新编码为 C 或 C++,并在那里修复它。这将使更多种类的程序员更容易使用它。我正准备用整个 LAPACK 发行版(你可能已经注意到)来做这件事——大约 500000 到 1000000 行。

C等价的结构,本身也是建立多维数组的最佳方式。你只为整个事情分配一个基本段。然后,对于第二个维度,您将一段指针分配到其中 - 一个栅格。然后,对于第三个维度,您将一段指针分配到那个......等等。

等价语句本身没有良好的 C 等价性。(地球幽默。Ork。Ork。)相反,在使用引用类型的 C++ 中最好找到等价的等价物。在 C++ 中,您还可以更直接地呈现 Fortran 下标,因为下标本身(带有 [] 和 () 类型括号)是可编程运算符。因此,您实际上可以直接将等价结构及其索引方法原样转换为静态结构,而无需进行上述分配。

于 2021-10-07T22:12:30.423 回答