Fortran 普通块

示例

在Fortran的早期形式中,用于创建从子例程和函数可见的全局变量存储的唯一机制是使用COMMON块机制。这允许变量序列成为名称并共享。

除了已命名的公共块之外,还可能有一个空白(未命名)的公共块。

可以声明一个空白的公共块,例如

common i, j

而命名块variables可以像

common /variables/ i, j

作为一个完整的示例,我们可以想象一个可以添加和删除值的例程使用的堆存储:

       PROGRAM STACKING
       COMMON /HEAP/ ICOUNT, ISTACK(1023)
       ICOUNT = 0
       READ *, IVAL
       CALL PUSH(IVAL)
       CALL POP(IVAL)
       END

       SUBROUTINE PUSH(IVAL)
       COMMON /HEAP/ ICOUNT, ISTACK(1023)
       ICOUNT = ICOUNT + 1
       ISTACK(ICOUNT) = IVAL
       RETURN
       END

       SUBROUTINE POP(IVAL)
       COMMON /HEAP/ ICOUNT, ISTACK(1023)
       IVAL = ISTACK(ICOUNT)
       ICOUNT = ICOUNT - 1
       RETURN
       END


公共语句可用于隐式声明变量的类型并指定dimension属性。仅此行为通常就足以引起混乱。此外,隐含的存储关联和跨程序单元重复定义的要求使得使用容易出错的通用块成为可能。

最后,公共块在它们所包含的对象中非常受限制。例如,公共块中的数组必须具有显式的大小。可分配的对象可能不会出现;派生类型不能具有默认初始化。

在现代的Fortran中,可以使用模块来处理变量的共享。上面的例子可以写成:

module heap
  implicit none
  ! In Fortran 2008 all module variables are implicitly saved
  integer, save :: count = 0
  integer, save :: stack(1023)
end module heap

program stacking
  implicit none
  integer val
  read *, val
  call push(val)
  call pop(val)

contains
  subroutine push(val)
    use heap, only : count, stack
    integer val
    count = count + 1
    stack(count) = val
  end subroutine push

  subroutine pop(val)
    use heap, only : count, stack
    integer val
    val = stack(count)
    count = count - 1
  end subroutine pop
end program stacking


命名和空白公共块的行为略有不同。注意:

  • 命名的公共块中的对象可以最初定义;空白共同对象不应

  • 空白公共块中的对象的行为就像公共块具有save属性一样;save当该块不在活动程序单元的范围内时,没有属性的命名通用块中的对象可能会变得不确定

后一点可以与现代代码中模块变量的行为形成对比。当模块超出范围时,Fortran 2008中的所有模块变量都会隐式保存,并且不会变得不确定。在Fortran 2008之前,模块超出范围时,诸如命名公共块中的变量之类的变量也将变得不确定。