Fortran newbie here, I've been asked to work on an old Fortran codebase written in Fortran 77 with Salford/Silverfrost compiler (the original developer passed away).
The original developer uses named COMMON
blocks extensively (to emulate global variables, AFAIU) and he uses EQUIVALENCE
to (re-)initialize the blocks when needed like in this code snippet:
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
Is this an acceptable programming practice or just a hack? Also, since I'm trying to port the code to GFortran, is it portable? (I understand that declarations like REAL*8
are just hints to the compiler and not guaranteed)
EQUIVALENCE
doesn't do anything, it certainly doesn't intialise anything, anEQUIVALENCE
is a definition or declaration. These days (and ever since the publication of the Fortran 90 standard with a force growing all the time)EQUIVALENCE
is a hack, and should be avoided wherever possible.The statement declares that 2 variables share storage (what the Fortran standards call storage-association). One interpretation of this is that the names which are equivalenced are simply aliases, but the (ab-)use of the statement allows the programmer to do some other things which are regarded, by 21st century professional software engineers, as well-dodgy.
For example, and this applies in the snippet you've posted,
EQUIVALENCE
can be used to have variables of different types share the same storage. You have an array calledASCN
which is (implicitly) of typeREAL*8
equivalenced to an array calledKLCKF2D
which is (again implicitly) of typeINTEGER
. What this means is that if you refer to the storage under one name the bit-patterns are interpreted asREAL
s, using the other name they areINTEGER
s -- and note that the bit pattern for a real with the value100.0
will not (of course) be interpreted as the integer100
.And the hackery doesn't stop there. One effect of the
COMMON
block declaration is to lay the variables out in memory, in your case the10500 (= 100*21*5)
elements ofASCN
are followed by the8700
elements ofFEMPTY2
. With a little multiplication and addition you find that38400 = 2*(10500+8700)
which accords with the default integer size in this program being 4-bytes, ie half the size of theREAL*8
s used in the other variables. So the arrayKLCKF2D
is larger thanASCN
but the original programmer knew that the next17400
bytes would be occupied byFEMPTY2
.So yes, this may be a way of setting all the bits in that part of your program's in-memory data to
0
, but it's (now considered to be) a horrid hack. But it should be portable -- successive Fortran standards have been very conservative about deleting obsolete features from the language and compiler-writers even more so, backward-compatibility is VERY important to Fortran programmers.Oh, and to answer your question, yes
COMMON
blocks were (note the past tense) the FORTRAN77 way of declaring and using global variables. These days the language offers the much safer option of declaring variables to be shared globally by wrapping them in aMODULE
andUSE
-associating them.I wouldn't have been surprised to see a line like
in your code,
COMMON
blocks can also be (ab-)used to rename and retype storage locations.While I'm giving your old code a kicking, implicit typing is also frowned upon these days, far better to explicitly type all declarations.