Fortran声明时的赋值和SAVE属性问题

21
在Fortran 95中,如果您在声明时分配一个变量
integer :: var = 0

它等同于

integer, save :: var = 0

因此,在例程执行后变量被保留(相当于C中的static),并且在再次调用时不会重新初始化。这种(我认为很危险的)行为背后的原理/技术问题是什么?


2
为了完整起见,让我提一下,在Fortran 2003标准中,您提到的点在C1107中得到了涵盖:“如果指定了组件初始化(R444)的类型的对象出现在模块的规范部分中,并且没有ALLOCATABLE或POINTER属性,则该对象必须具有SAVE属性。”。 - Alexandros Gezerlis
@Alexandros Gezerlis - 没错,但他正在问他们为什么这样做,现在我理解了他的问题,我也有同样的问题 :)。 - dcp
我知道,这就是为什么我没有把它发布为答案的原因。 - Alexandros Gezerlis
2个回答

12

我认为这种行为背后没有任何合理的解释。

但据我所知,Stefano,你使用了错误的术语。在你的代码中,没有赋值语句,只有使用初始化表达式(0)对变量(var)进行初始化。

integer :: var = 0 ! type declaration & initialization

integer :: var ! type declaration
var = 0        ! assignment

看起来这只是委员会的设计决策。如果我们有这样的表达式(在类型声明语句中带有等号),那么它就是初始化而不是赋值。而初始化仅在程序执行期间(而不是过程)进行一次。

然而,这样的决定可能有一些历史原因。请看线程。

如今,这种行为是危险的,因为许多其他广泛使用的语言遵循了另一种关于初始化/赋值的约定。


1
如果这是一个故意的设计决定,那么我是否应该发表一个问题:“Fortran委员会成员在决策会议期间被允许吸什么?” :)开玩笑的。我不认为他们犯了如此严重的错误,所以一定有理由,可能与兼容性或技术问题有关。这似乎太奇怪了,不能仅仅是为了设计而做出的决定。 - Stefano Borini
1
@Stefano:也许有一些历史原因,而不是不吸烟。=)阅读此线程:http://www.rhinocerus.net/forum/lang-fortran/92384-initialization-local-variables.html - Wildcat
我认为你说得很到位!请编辑你的回答并包含链接。 - Stefano Borini
1
该链接现在已经失效。文章的要点是什么? - Christoph90
@Wildcat,对于Fortran标准的更改,J3总是有一个合理的解释。您可以在https://j3-fortran.org/doc/year上找到至少可以追溯到1987年的文件。如果您查看(我不会查看),我猜您会发现'real :: x = 42.'旨在替换'real x'后跟'data / x / 42.'的两个语句。 (这里'data'语法可能会出错,因为我很少使用'data'语句。)因此,初始化表达式的语义从“data”语句继承。 - steve

10

很多旧的FORTRAN 77和之前的编译器都是静态分配所有变量。很多程序员都依赖这种行为--这在他们的程序里技术上是一个漏洞,因为除非他们在声明中使用“SAVE”修饰符(或在每个过程中添加一个普通的SAVE语句),否则变量的值在重新进入过程时是不确定的。但由于在那个年代,程序往往与特定平台和编译器绑定多年,程序员得以逃脱惩罚。将传统FORTRAN 77代码移植到现代Fortran >= 90编译器时,这是一个非常常见的“陷阱”。大多数编译器提供编译时开关来恢复此行为,例如gfortran的fno-automatic选项。最可能的是委员会认为在声明中初始化的变量非常可能需要SAVE属性--在我看来,这是一个合理的设计决策。我认为与其他语言最不同、最容易混淆的是,初始化只进行一次。


Fortran 77标准没有规定是否会发生重新初始化。我使用了两种编译器;没有SAVE的初始化做法是不可移植的。我记得看到过一份声明,委员会认为单独的赋值清楚地处理了重新初始化的情况,并允许应用或删除SAVE限定符而不影响结果,而只初始化一次的行为在标准中选择其他选项时无法实现。 - tim18

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接