常见块
在 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 模块变量(如命名公共块中的变量)之前,当模块超出范围时,它们也将变为未定义。