A candidate for the title of "Strangest Thing in Computer Science" would be the fact that FORTRAN lets you change the value of what appear to be unalterable numbers. Plato would roll over in his grave.

I have heard rumors that later FORTRAN compilers had this "capability" designed out. But the venerable FORTRAN IV and FORTRAN 77 allowed you to do it. Anyway, people who have written new code in FORTRAN after about 1985 have got to be another set of candidates for the title.

The problem stems from the intersection of two decisions made for the implementation of FORTRAN:

  • Literal constants are not put into code inline. Instead, they are allocated an area of memory which is then assigned the value. That is, in FORTRAN, '5' behaves like a variable. An expression containing a literal 5 references the memory area allocated for it.
  • All parameters to subroutines and functions are passed by reference.

Thus, a subroutine that changed the value of one of its parameters could silently change a literal constant.


C      
C     CHANGE THE VALUE OF 5
C

      CALL TWEAK (5)
      WRITE (10, 30) 5
30    FORMAT (I5) 
      END

C
C     SUBROUTINE TWEAK: 
C

      SUBROUTINE TWEAK (I)
      I = I + 1
      END

Run this program on an old-enough FORTRAN compiler and it will output:

00006

How do you avoid this problem? You can always use another variable, assign 5 to it, then call the subroutine using the variable as a parameter. But I learned a much more interesting solution while taking a computer cartography course in college. I was taking it concurrently with a CS class using the coolest language of the day, Pascal. But in the cartography class, all the code was to be written in FORTRAN. I was, to say the least, disgruntled at having to use such a Neanderthal language. Nevertheless, I bore my terrible burden. Anyway, I was oblivious to the default pass-by-reference behavior of subroutines when I introduced an expression as a parameter to a CALL:

      CALL GENERALIZE (IXARRAY, IYARRAY, IANCHOR)

The compiler gave me a warning message for this construct. Something like: WARNING: SUBROUTINE GENERALIZE IS LIKELY TO CHANGE THE VALUE OF PARAMETER IANCHOR. Mind you, GENERALIZE didn't actually change the value of that parameter, but static flow analysis was not a strength of this compiler.

Today, this still leaves me shaking my head. The compiler writers went to the trouble of detecting this condition, and inserting a diagnostic message to warn about it. But they couldn't make the compiler emit a constant value inline?

My class instructor, (a cartographer, remember) had no idea what the warning meant, but told me to get rid of the warning for a passing grade. The manual was cryptic. My only recourse was that spectre of terror, the Computer Center help desk. After laughing at my little problem, FORTRAN's little bonus feature was explained to me, and I was told since my subroutine didn't actually modify the parameter, that I shouldn't worry about it.

I have to admit, the youthful Gorgonzola was a perfectionist. I pressed them on how to get rid of the problem. After an annoyed look, the answer was "Oh, put parentheses around the expression." Thus:

      CALL GENERALIZE (IXARRAY, IYARRAY, (IANCHOR))

Sure enough, no more warning message. When you put the expression in parentheses, the compiler creates another temporary memory area in which it stores the result of ANCHOR+1 before calling the subroutine. This jiggled the compiler enough for it to realize there was no danger.

In the end, my project was marked down for using unnecessary parentheses.