views:

58

answers:

1
  Program ConstTest;
  Const constVar = 1;
  Begin
    constVar := 3;
    WriteLn(constVar);
  End.

It's pretty obvious that the above code will not compile, because it's not right to change the value of a constant. However, following code will compile, and will return "1; 5; 3;", even though the array is a const:

Program ConstTest;
  Const constArr:Array [1..3] Of ShortInt = (1,2,3);
  Var i:ShortInt;
  Begin
    constArr[2] := 5;
    For i:=1 To 3 Do WriteLn(constArr[i],'; ');
  End.

So, what causes this behavior? Why a constant isn't actually a constant?

I'm using FreePascal Compiler 2.2.0 for Win32.

+5  A: 

What you have there is a typed constant. Typed constants are distinct from ordinary constants (a.k.a. true constants), which is what your constVar is. Notice how you didn't need to specify a type on constVar; if you had, you may see that the compiler allows you to assigned new values to it, too:

const
  constVar: Integer = 1;

The Free Pascal manual describes typed constants:

Contrary to ordinary constants, a value can be assigned to them at run-time. This is an old concept from Turbo Pascal, which has been replaced with support for initialized variables: For a detailed description, see section 4.4, page 183.

Support for assigning values to typed constants is controlled by the {$J} directive: it can be switched off, but is on by default (for Turbo Pascal compatibility). Initialized variables are always allowed.

For an initialized variable, replace const with var in your declaration. It will get its value upon entering scope. Or, turn off the $J directive prior to the typed-constant declaration:

{$J-}
const
  constArr: array [1..3] of ShortInt = (1, 2, 3);
{$J+}

Whether you turn it back on afterward is up to you.


Typed constants are modifiable because of the way they're stored in memory. In fact, it's because they're stored in memory that they were originally modifiable. Ordinary constants aren't stored in memory as distinct objects. When the compiler encounters an ordinary constant used in your program, it replaces it in-line with the constant's value, just as though you'd used a literal in its place. A typed constant, on the other hand, resides in its own location in memory, and when you refer to one in code, its value is read from memory, just like using any other variable. You use typed constants when there is no syntax available for a literal — you can't have array or record literals, for instance.

Rob Kennedy