-1

This is the first piece of code, that outputs 44:

const int a[] = {3};
int* b = (int*)&a[0];
*b = 4;
cout << a[0] << *b;

And this is the second, that outputs 34:

const int a = 3;
int* b = (int*)&a;
*b = 4;
cout << a << *b;

I have no ideea why is there a difference. Can you guys explain this?

  • 7
    Undefined Behaviour is undefined. Do not try to find logic in it. – Yksisarvinen Jun 10 '19 at 19:08
  • @Yksisarvinen why would this be undefined behavior? Also, I had a question similar to this for college, and then I started to play with some code. And got to this. That's why I'm trying to find the logic. – SolcanMihai Jun 10 '19 at 19:09
  • 3
    You are modifying a variable you declared as const. As such your programs have undefined behaviour. It's absolutely not the case that they 'should work the same'. In fact you are as far from that as it's possible to get. – john Jun 10 '19 at 19:09
  • 1
    `*b = 4;` is trying to modify an object that is defined to be `const` in both cases (`const int a` and `const int a[1]`) . Both of these programs can do whatever they want with no justification. Edit : Normally the compiler prevents you from trying to do this, but `(int*)` is explicitly telling the compiler to mind its own business and ignore your mistakes. – François Andrieux Jun 10 '19 at 19:09
  • 3
    Remove the cast to `int*` and your compiler will probablly be friendly enough to tell you: `invalid conversion from ‘const int*’ to ‘int*’` in both cases. – Ted Lyngmo Jun 10 '19 at 19:12
  • 1
    That's undefined behavior for you. If you disassembled the compiled code or used single step in your debugger you might see how the compiler chose to behave, but any behavior is correct when you do things like this. If your computer explodes and pierces you with jagged shrapnel you still can't complain as your lifeblood trickles away. – Dave S Jun 10 '19 at 19:12
  • 2
    @SolcanMihai Any logic you can find will depend on the details of the compiler you are using. A different compiler would in all likelihood produce different results with these programs. All the C++ standard has to say is that the behaviour is undefined. – john Jun 10 '19 at 19:13
  • 1
    @DaveS or you could even get some [demons flying out of your nose](http://catb.org/jargon/html/N/nasal-demons.html) – Yksisarvinen Jun 10 '19 at 19:14
  • Someone correct me if I'm wrong, but you can modify a const in a defined way using [const_cast](https://www.geeksforgeeks.org/const_cast-in-c-type-casting-operators/) if you need to, though it still isn't recommended. –  Jun 10 '19 at 20:11

2 Answers2

2

A pointer to a variable declared as const can be assigned only to a pointer that is also declared as const. You are breaking the rule and ideally your compiler should prevent you from doing so.

none of gcc, clang, and MSVC prevent such a mistake and as mentioned in the comments you have undefined behavior instead of at least a warning. However zapcc compiler will make your program to crash with a Segmentation fault.

Oblivion
  • 7,176
  • 2
  • 14
  • 33
1

Besides invoking "undefined behavior" by using casts to circumvent the compiler's checks to change the value of a const variable, the observed result can be explained with the optimizations the compiler likely did:

In the first case, you declare a const array, which likely ends up as data somewhere in RAM.

In the second case, you have a single scalar const value and the compiler probably decided to just use the constant's value which is known at compile time in the output instead of reading that known value from a RAM location. This optimization is also known as constant propagation. If you didn't take the address of a in your code, it's value would probably not even have a location in data RAM allocated.

JimmyB
  • 12,101
  • 2
  • 28
  • 44