Consider the following code :
My_Constant : constant := 2;
Is "My_Constant" a variable or a C language macro-like, so does it have a storage in memory ?
Note that constant
just means that you cannot modify the object. It doesn't necessarily mean that the value of the constant is known at compile time. So there are three cases to consider:
(1) A constant with a type, whose value is known at compile time:
My_Constant : constant Integer := 3;
In this case, there's no reason for the compiler to allocate memory for the constant; it can use the value 3 whenever it sees My_Constant
(and is likely to use 3 as the immediate operand of instructions, where possible; if it sees something like My_Constant * 2
then it can use the value 6 as an immediate operand). The compiler is allowed to allocate memory for the constant, but I don't think any decent compiler would do so, in a simple case like this with a small number. If it were a really large number that wouldn't fit into an immediate operand, it might make more sense to allocate space for the number somewhere (if it can do so in a way that saves on code space).
In a more complex case:
My_Record_Constant : constant Rec := (Field_1 => 100, Field_2 => 201, Field_3 => 44);
Here, a good compiler can decide whether or not to store the constant in memory based on how it's used. If the only uses are accesses of individual fields (My_Record_Constant.Field_1
), the compiler could replace those with the integer values, as if they were integer constants, and there would be no need to store the entire record in memory.
However, using aliased
will cause any constant to be forced into memory:
My_Constant : aliased constant Integer := 3;
Now memory has to be allocated because the program could say My_Constant'Access
(the access type has to be access constant Integer
).
(2) A constant whose value is not known at compile time:
My_Constant : constant Integer := Some_Function_Call (Parameter_1);
The function is called once, when the integer's declaration is elaborated. Since it is not a macro expansion, uses of My_Constant
do not generate calls to the function. Example:
procedure Some_Procedure is
My_Constant : constant Integer := Some_Function_Call (Parameter_1);
begin
Put_Line (Integer'Image (My_Constant));
Put_Line (Integer'Image (My_Constant));
end Some_Procedure;
Some_Function_Call
is called each time Some_Procedure
is called, but it is called once, not two or three times.
Most likely, this requires the value to be stored in memory to hold the function result, so space will be allocated for My_Constant
. (This still isn't a requirement. If a good optimizing compiler can somehow figure out that Some_Function_Call
will return a known value, it can use that information.)
(3) A named number. This is the example you have, where there is no type:
My_Constant : constant := 2;
The language rules say the value must be known at compile time. This is the equivalent of using that number every time My_Constant
is seen, so it's the closest thing to a C macro you're going to get in Ada. But the effect is basically the same as in (1) [except with fewer restrictions on type compatibility]. The compiler probably will not allocate space for it, but it might do so for a larger value. Note that this syntax is allowed only for numeric values (integer or real).
Another variation on option (1) above is for a constant array.
primes : constant array(integer range <>) of integer := (1, 3, 5, 7, 11, 13, 17, 19, 23);
If the compiler can see it being accessed by an index, it will have to store the array. I doubt the compiler writers would try and special case any other obscure corner condition to save some memory - they have enough other special corner cases to worry about in Ada!