Constants, Typed Constants & Variables

True constants have no storage; the compiler substitutes their values and can evaluate constant expressions using Ord, Chr, Length, SizeOf, Low, High, Trunc, Round, arithmetic, and more.

6.1 Constants

True constants have no storage; the compiler substitutes their values and can evaluate constant expressions using Ord, Chr, Length, SizeOf, Low, High, Trunc, Round, arithmetic, and more.

const
  Pi2 = 2 * Pi;                       // constant expression
  AppName = 'Inventory';
  MaxUsers = 100;
  Vowels = ['a', 'e', 'i', 'o', 'u']; // set constant
  Debug = False;

6.2 Typed constants

Typed constants are initialized variables with static storage. Whether they can be assigned is controlled by {$J} / {$WRITEABLECONST}:

FPC: writable by default ({$J+}).

Delphi: read-only by default ({$J-}) since Delphi 7.

A classic use of writable typed constants is a counter that keeps its value between calls:

Prefer a unit-level variable or a class variable in new code.

const
  Primes: array[1..5] of Integer = (2, 3, 5, 7, 11);
  Origin: record X, Y: Integer; end = (X: 0; Y: 0);
  DefaultName: string = 'Guest';
{$J+}
function NextId: Integer;
const
  Counter: Integer = 0;
begin
  Inc(Counter);
  Result := Counter;
end;
{$J-}

6.3 Resource strings

Stored as resources so they can be translated (Delphi ITE, Lazarus .po files).

resourcestring
  SFileNotFound = 'File "%s" not found';

6.4 Variables

Global variables (program or unit level) are zero-initialized.

Local variables are not initialized — except managed types (strings, dynamic arrays, interfaces, Variants), which start empty/nil.

Delphi 10.3+ supports inline variables with type inference (not supported by FPC):

var
  Count: Integer;
  Price, Tax: Double;
  Name: string;
  Done: Boolean = False;     // initialized global variable (FPC and Delphi)
// Delphi 10.3+ only
begin
  var Total := 0;                 // inferred Integer
  for var I := 1 to 10 do
    Inc(Total, I);
  const Msg = 'Sum: ';
  Writeln(Msg, Total);
end;

6.5 Absolute variables

var
  B: Byte;
  C: Char absolute B;   // C shares B's memory (low-level trick; rarely needed)

6.6 Scope

Identifiers declared in a block are visible from their declaration to the end of the block, including nested routines.

Inner declarations hide outer ones with the same name.

Unit interface declarations are visible to every unit that uses it.

Use the unit name to disambiguate: System.Writeln, MyUnit.Count.