0

I'm trying to understand pointers and I encounter this example.

If I have int MAX_VALUE = 90; the program behaves like I expected. But with const int MAX_VALUE = 90; it doesn't.

What is the explication?

#include <iostream>

using namespace std;

int main()
{

    const int MAX_VALUE = 90;

    cout << "Create variable in the heap." << endl;
    int* a = new int;
    *a = 2;

    cout << "Point a to MAX_VALUE" << endl;
    a = (int*)&MAX_VALUE; // Now a points to MAX_VALUE

    cout << "Change content of a" << endl;
    *a = 6; // Shouldn't this change the value of MAX_VALUE ??

    cout << "Content of a: "<< *a << endl;
    cout << "MAX_VALUE: " << MAX_VALUE << endl;

    return 0;
}

Result:

Content of a: 6
MAX_VALUE: 90

But shouldn't MAX_VALUE change when I did *a = 6;?

I know you can't change const, but how does C++ handle it? I have a pointing to MAX_VALUE, how can I change a and not MAX_VALUE?

cara ash
  • 107
  • 6
  • 6
    You cannot change a `const`, and attempting to do so is undefined behavior. – Eljay May 21 '20 at 11:00
  • Does this answer your question? [Undefined, unspecified and implementation-defined behavior](https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior) – KamilCuk May 21 '20 at 11:04

5 Answers5

1

As others have said, you're exploiting undefined behavior. In your case, your program is able to execute without crashing because your compiler's linker allocated space for the "constant" MAX_VALUE in RAM, and it was allocated in a RAM region whose attributes are not set as "read-only". I.e. it's being placed in writable RAM, even though you've declared it as const.

On another system, MAX_VALUE might be allocated in ROM (e.g. in an embedded system where the entire program is stored in memory-mapped flash space, and never copied to RAM). On such a system, you could try to write to MAX_VALUE all you wanted and it would never change, unless you knew the magic incantation pattern to trigger the flash memory's erase/program operations, in which case, yes it would change, but not to the value you wanted to change it to. (And if you triggered an erase operation, a whole lot of bytes around it would quickly change to all 0xFF's!) But that's really only possible on primitive embedded systems where the ROM address space isn't write-protected by an MMU, MPU, or by its chip-select configuration.

On yet another system, MAX_VALUE might be allocated in RAM, but in a section that's marked as read-only in the MMU/MPU. So even though the hardware would be physically capable of allowing its value to change at runtime, it is configured to trap/catch any attempt to do so, and will crash your program for an illegal access attempt (or other similar wording).

But as I said, on your system, since you can change the value of MAX_VALUE at runtime (bypassing compiler safety by casting away its const attribute), we know that on your system MAX_VALUE is allocated in writable RAM.

But then you're of course asking, how could the line...

cout << "MAX_VALUE: " << MAX_VALUE << endl;

...print 90 when you had previously changed its value to 6? Well, the compiler is allowed to optimize that line by not even performing a read of MAX_VALUE, using instead the initialization value from its definition, since in this compilation unit its initialization value is known. The const qualifier is a promise to the compiler that you won't be changing it, and at the same time, a request to the compiler that it alert you if you ever mistakenly try to change it. But by casting away the const attribute, you're bypassing that safety and the result is undefined behavior according to the C++ standard. In your case, your system will execute the code without crashing for the reasons I mentioned above.

phonetagger
  • 7,701
  • 3
  • 31
  • 55
0

It is because of compiler optimization. Since you have declared it as 'const', the compiler has optimized the "cout" to the actual value 90. So, it will not really use the value stored as MAX_VALUE. But I don't know why it is done even if we switch off the optimization.

If you watch the disassembly, you can see that the real value pushed is '5A' which is hex of 90

Manoj AV
  • 119
  • 4
0

The problem is not so much that you are not allowed to change the value of *a but that the assignment of a const int* to an int* is not allowed by the C++ standard. If you remove your c-style cast the compiler will tell you so:

error: invalid conversion from ‘const int*’ to ‘int
15 |     a = &MAX_VALUE; // Now a points to MAX_VALUE
   |         ^~~~~~~~~~
   |         |
   |         const int*

The reason that the compiler accepts your original code but produces a result that differs from your expectation is that casting away constness can lead to undefined behaviour (as it does in this situation).

The standard states in [dcl.type.cv] 10.1.7.:

  1. Except that any class member declared mutable (10.1.1) can be modified, any attempt to modify a const object during its lifetime (6.8) results in undefined behavior.

(emphasis added)

And in your code MAX_VALUE refers to a const object, regardless of how you access it (e.g. through a).

Undefined behaviour means that while the compiler accepts the program and turns it into something, it is not defined what the result of this conversion is. For any program that exhibits undefined behaviour, the compiler is allowed to do literally anything it sees fit with your code. See also nasal demons.

bitmask
  • 32,434
  • 14
  • 99
  • 159
-1

As,you make MAX_VALUE as constant integer.You cannot change its value if once its value is specified. You can learn more about constants here: http://www.cplusplus.com/doc/tutorial/constants

Amit Nandal
  • 118
  • 1
  • 6
-1

Remove const from your code and problem will be solved

Constants refer to as fixed values, unlike variables whose value can be altered, constants - as the name implies does not change, they remain constant. Constant must have to be initialized at the time of creating it, and new values cannot be assigned later to it.

You can use the Variables if you want to alter the Value in it.

A variable provides us with named storage that our programs can manipulate and the set of operations that can be applied to the variable.