I would like to understand how C ++ handles constants of basic types.

What will happen if, with the help of the tambourine dances and pointers, the value in the memory cell is changed, where, in theory, a constant should be contained?

There is the following code:

#include <iostream> using namespace std; int main(int argc, char** argv) { const int number = 45; const int * constPoint = &number; cout << "constPoint " << constPoint << endl; int * point = (int *) constPoint; cout << " point " << point << endl; * point = 54; cout << "&number " << &number << "; number " << number << endl; cout << " point " << point << "; *point " << *point << endl; } 

The conclusion I get is the following:

 constPoint 0x7fff1b73a6ec point 0x7fff1b73a6ec &number 0x7fff1b73a6ec; number 45 point 0x7fff1b73a6ec; *point 54 

Thus, the value of the constant has not changed, although the number contained in the cell at the address of this constant is different.

How to explain this behavior?

I'm not going to use such code in practice, I just want to understand where the constants are stored.

    3 answers 3

    To begin with: according to the standard, changing with the help of tricks with constant pointers has undefined behavior. Anything at any point in the program can happen.

    The compiler has the right not to store a constant anywhere else if you don’t refer to it. Or has the right to store, if he thinks so better. Or stored in read-only memory. Or stored at a common address with some code instruction that is numerically equal to the same constant.

    For example, if the compiler sees a call to a constant, he can embed it in the call point (he knows the value at the compilation stage), he can access this constant at the address at any time, he can even express other constants through this (for example, if you have there is a constant 1024 , then it has the right to refer to 2048 as 1024 << 1 for reasons of efficiency).

    Worse, if somewhere the compiler found out for itself that the constant is even, and its low bit is 0, and based on this information could exclude any checks from the code, now the checks will not pass, and the code may crash at any time .

    UB is usually based on security holes. For example, if the compiler reasonably believes that the length of line 45 is enough to allocate a buffer of such length for it, while deceiving the compiler, you slip a string 54 in length, you get a classic stack stall.


    Summary: The compiler has no "obligations" or "principles" for working with constants. He has the right to do anything. On the contrary, this is a programmer, if he promised that some value is a constant, he has no right to change it.

    • And if you make a volatile const ? It seems somewhere it was written that this is normal. - Qwertiy ♦
    • 2
      @Qwertiy: Uh, what's the point of const , if you can change it? - VladD
    • 2
      It’s as if the statement that we don’t change this, and with an explicit assignment attempt there should be a compilation error. But at the same time, we say, do not dare to optimize access, the external code can change the value at any time. - Qwertiy ♦

    According to the C ++ standard (7.1.6.1 The cv-qualifiers)

    4 (7.4 ) results in undefined behavior.

    There is one anachronism in C, where even an attempt to change a non-constant object leads to an undefined program behavior. We are talking about string literals in C.

    In C ++, string literals have types of constant character arrays. For example, the string literal "Hello" has the type const char[6] . However, in C, string literals have types of non-constant character arrays. Therefore, the same string literal "Hello" in C is of type char[6] . However, you cannot change the string literal in C, just as you cannot change the string literal in C ++.

    From standard C (6.4.5 String literals)

    7 It is unspecified. The behavior is undefined.

    The fact that in C string literals have types of non-constant character arrays is obviously connected with the support of the already existing code base at the time of introducing the const qualifier into the C standard.

      The compiler is smart and knows that the constant can be zainlaynit. But it is possible to convince him that this constant is not too constant:

       volatile const int number = 45; 

      Full code: http://codepad.org/tNlZoNkE
      Option with custom in void* for output: http://codepad.org/EoqOgd6t

      PS: As far as I remember, volatile const is a valid situation that should not lead to an undefined behavior.

      he has every right to assume that his code does not exactly change const-objects.

      For volatile it does not matter. Imagine that there is something external that “completely accidentally” changes the same constant to the same values ​​that we wrote. And in the program itself instead of the changing code are nop'y. This option is absolutely correct and does not cause UB.

      So, if UB is there, then it is caused by the unchanged value, but the write operation itself. Is there any case in which this is possible? Only the read-only page in memory comes to mind, but can the compiler do that? He will put the local variable on the stack, which is definitely not readonly. Remain global. (Fields of objects fall into one of these categories.) Or are there still situations where a write operation can spoil something?

      • Can you provide a link to the standard? In the answer, Vlad from Moscow is affirmed with the reference that const cannot be changed. - VladD 10:49 pm
      • I looked at the section 7.1.6.1 of the standard and did not find confirmation there that the const volatile object can be changed. There is only an indication that he has the right to change the way external to the program, which is not the same thing. - VladD
      • @VladD, found only such information: phy.duke.edu/~rgb/General/c_book/c_book/chapter8/… en.cppreference.com/w/cpp/language/cv embeddedgurus.com/barr-code/2012/01 / ... In the third link, one of the examples is the communication of two handlers via shared memory when we just read. - Qwertiy ♦
      • one
        Hm I think your argument about UB is wrong, the compiler does not work that way. He has the right to assume that UB never happens. Therefore, if he can prove that the code modifies the const variable, he has every right to assume that this code will never be executed, and throw it away. - VladD
      • one
        @VladD, asked a question in English SO: stackoverflow.com/q/31527499/4928642 - Qwertiy ♦