I copied some Delphi code from one project to another, and found that it doesn't compile in the new project, though it did in the old one. The code looks something like this:
procedure TForm1.CalculateGP(..) const Price : money = 0; begin ... Price := 1.0; ... end;
So in the new project, Delphi complains that "left side cannot be assigned to" - understandable! But this code compiles in the old project. So my question is, why? Is there a compiler switch to allow consts to be reassigned? How does that even work? I thought consts were replaced by their values at compile time?
Constants are block-scoped, much like variables declared using the let keyword. The value of a constant can't be changed through reassignment (i.e. by using the assignment operator), and it can't be redeclared (i.e. through a variable declaration).
To declare a record constant, specify the value of each field - as fieldName: value , with the field assignments separated by semicolons - in parentheses at the end of the declaration. The values must be represented by constant expressions.
The constant variable values cannot be changed after its initialization. In this section we will see how to change the value of some constant variables. If we want to change the value of constant variable, it will generate compile time error.
You use the Const statement to declare a constant and set its value. By declaring a constant, you assign a meaningful name to a value. Once a constant is declared, it cannot be modified or assigned a new value. You declare a constant within a procedure or in the declarations section of a module, class, or structure.
You need to turn assignable typed constants on. Project -> Options -> Compiler -> Assignable typed Constants
Also you can add {$J+}
or {$WRITEABLECONST ON}
to the pas file, which is probably better, since it'll work even if you move the file to another project.
Type-inferred constants can only be scalar values - i.e. things like integers, doubles, etc. For these kinds of constants, the compiler does indeed replace the constant's symbol with the constant's value whenever it meets them in expressions.
Typed constants, on the other hand, can be structured values - arrays and records. These guys need actual storage in the executable - i.e. they need to have storage allocated for them such that, when the OS loads the executable, the value of the typed constant is physically contained at some location in memory.
To explain why, historically, typed constants in early Delphi and its predecessor, Turbo Pascal, are writable (and thus essentially initialized global variables), we need to go back to the days of DOS.
DOS runs in real-mode, in x86 terms. This means that programs have direct access to physical memory without any MMU doing virtual-physical mappings. When programs have direct access to memory, no memory protection is in effect. In other words, if there is memory at any given address, it is both readable and writable in real-mode.
So, in a Turbo Pascal program for DOS with a typed constant, whose value is allocated at an address in memory at runtime, that typed constant will be writable. There is no hardware MMU getting in the way and preventing the program from writing to it. Similarly, because Pascal has no notion of 'const'ness that C++ has, there is nothing in the type system to stop you. A lot of people took advantage of this, since Turbo Pascal and Delphi did not at that time have initialized global variables as a feature.
Moving on to Windows, there is a layer between memory addresses and physical addresses: the memory management unit. This chip takes the page index (a shifted mask) of the memory address you're trying to access, and looks up the attributes of this page in its page table. These attributes include readable, writable, and for modern x86 chips, non-executable flags. With this support, it's possible to mark sections of the .EXE or .DLL with attributes such that when the Windows loader loads the executable image into memory, it assigns appropriate page attributes for memory pages that map to disk pages within these sections.
When the 32-bit Windows version of the Delphi compiler came around, it thus made sense to make const-like things really const, as the OS also has this feature.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With