Storage Allocation for Constant Variables

I read a book that mentions this

If the compiler knows every use of the constant, it does not need to be allocated to hold it. For instance:

  • const int c1=1;
  • const int c3=my_f(3);
  • extern const int c4;

Given that the values โ€‹โ€‹of c3 and c4 are not known as compilation time, storage should be allocated for c3 and c4.

I did not understand anything. My doubts:

What does it mean holding here? Wasnโ€™t it necessary to store everything in memory? For c1, if we do not have a memory allocation?

Please clarify my doubts.

Thanks.

+6
source share
3 answers

c1 differs from the other two constants in that it is initialized with a literal value. This allows the compiler to place this value wherever a constant is used, for example:

 int x = z + c1; 

can be replaced by

 int x = z + 1; 

This means that the compiler does not need to allocate space and store 1 in it.

c3 and c4 are different: one is calculated using a function, and the other from another compilation unit. This means that the compiler can not perform the substitution as he could, with the help of c1 : the values of c3 and c4 are not known to the compiler. Therefore, the compiler generates code for

 int x = z + c4; 

just as if c4 were a variable stored in some place in memory. Since c4 is an external constant in this case, the linker will resolve its location and fill in information that is not in the compiler (namely, address c4 ) to make the program complete and ready to run.

+4
source

Const has 2 use cases - replacing macros (constant expressions), as well as immutable data.

This statement:

 const int c1=1; 

This is essentially a security type version:

 #define c1 1 

To this code:

 int foo = c1; 

It can be simply compiled as:

 int foo = 1; 

Which is more efficient.

On the other hand, these are:

 const int c3=my_f(3); 

Used as immutable c3. It probably exists in memory, but you cannot change it. This is essentially a safer option int c3=my_f(3); .

To illustrate this:

 int a1[c1]; int a2[c3]; 

a1 is valid because the compiler can output a1 as a constant expression. a2 is not, since while c3 is const, it cannot be known at compile time.

C ++ 11 adds the constexpr keyword, which is similar to const , although it is more stringent than const . Only c1 and c2 can be constexpr . c3 may also be, although my_f required for this.

+2
source

As an integral expression of constants, the compiler has every right to use permanent folding to remove it from the program. This is not the case if you accept his address. In addition, the modern optimizing compiler can use LTO, inlining, and persistent folding to do the same with c3 and c4, if possible.

If you do not take the address of a variable, the compiler is not required to allocate it if it can generate code with equivalent results in accordance with the as-if rule.

Edit: persistent folding is where the compiler evaluates expressions at compile time rather than at run time. For example, you can legally execute int x[3 + 4]; where 3 + 4 is evaluated at compile time. Some examples, especially those related to MCOs, are standardized, but implementation can do more if possible. LTO is the optimization of communication time when the compiler performs optimization between translation units when they are connected to each other.

This means that the compiler can embed the body my_f , and then (depending on the body) the constant collapse it to make c3 constant expression, and then constantly dump it to where it was used, rather than highlighting It. For c4 the LTO can provide value c4 as a constant expression, and in this case it can also be folded and removed.

C ++ 11 has constexpr functions that allow you to do much more in this area.

+1
source

Source: https://habr.com/ru/post/905974/


All Articles