Whats the difference between between save, static, global, local and parameter variables?
Save and static are two words for the same thing.
I found a nice definition of what save do in the Fortran 77 Standard [1]
Within a function or subroutine subprogram, an entity specified by a SAVE statement does not become undefined as a result of the execution of a RETURN or END statement in the subprogram
subroutine func()
implicit none
real, save :: time
time = time + 1
write(*,*) time
end subroutine
program test
implicit none
integer :: i
do i = 1, 10
call func()
end do
end
1.00000000
2.00000000
3.00000000
4.00000000
5.00000000
6.00000000
7.00000000
8.00000000
9.00000000
10.0000000
You can count how often a subroutine is called. If you ever want to do this... I can not recommend to do it in this way.
As you may have noticed, I have not initialized the time variable with an start value.
You can do this with the data instruction.
subroutine func()
implicit none
real :: time
data time/100/
time = time + 1
write(*,*) time
end subroutine
101.000000
102.000000
103.000000
104.000000
105.000000
106.000000
107.000000
108.000000
109.000000
110.000000
The save specifier is not needed by using the data keyword.
This may result in confusion, because not everybody knows exactly what the data specifier does.
Again: do not use it.
The greatest pitfall with static variables is this:
real :: time = 0
If you initialize a variable by the declaration, it become a static variable! That really really hurts. You want be a good programer and always zero your variables and then you crash the hole program :D
Lets talk about parameters. Many programmers declare they constans with the save attribute.
I can not recommend this.
First: Constants does not change. Variables with save attribute can change.
real, save :: PI = 3.14...
PI = 4
All fine ;)
If you use parameter instead of save the compiler can detect this issue.
real, parameter :: PI = 3.14...
PI = 4
PI = 4
1
Error: Named constant 'pi' in variable definition context (assignment) at (1)
Second: Fortran is a high performance language. You can easily vectorize assigments using the forall constrcut.
All functions called from the forall constrcut must be declared as pure. to ensure that they have no side effects.
function func() result(val)
implicit none
real, save :: PI = 3.14
real :: val
val = PI
end function
forall( i = 1:100 ) A(i) = func()
forall( i = 1:100 ) A(i) = func()
1
Error: Reference to non-PURE function 'func' at (1) inside a FORALL block
And a pure function can not have static variables
pure function func() result(val)
implicit none
real, save :: PI = 3.14
real :: val
val = PI
end function
real, save :: PI = 3.14
1
Error: SAVE attribute at (1) cannot be specified in a PURE procedure
Using parameter solves the issue
pure function func() result(val)
implicit none
real, parameter :: PI = 3.14
real :: val
val = PI
end function
forall( i = 1:100 ) A(i) = func()
$ ifort -O2 -c save.f90 -vec-report3
save.f90(19): (col. 25) remark: LOOP WAS VECTORIZED
The last thing I talk about are global variables.
They can be accessed and overwritten from everywhere by everyone anytime. Happy bug chasing...
One way to create global variables in Fortran is using the COMMON keyword. I allready wrote about that..
[1] http://www.fortran.com/fortran/F77_std/rjcnf-8.html#sh-8.9