-1
const int z = 420;

printf("\n%d | %d",z ,*(&(*(&z+1))-1) );
// O/P:420 | 420

printf("\n%u | %u",&z,(&(*(&z+1))-1) );             //address
// O/P:1310548  | 1310548

*((char *)&z+1) = 21;       //I change value for the 1st-Bit
                                    //corrupting constant

 printf("\n%d | %d",z ,*(&(*(&z+1))-1) );
//the complex(not really) expression evaluates to z
// O/P:420| 5540

printf("\n%u | %u",&z ,(&(*(&z+1))-1) );                
//the complex(not really) expression evaluates to &z
// O/P:1310548 | 1310548

Why is this happening?

it seems that I have successfully modified constant in C

by modify I mean I have changed the bits in the constants address range

as the "complex(not really) unity/identity expression" changes value after corruption.

but the z remains same. Why?

how come same address have different values when de-referenced. ?

PS: u can use any identity expression

eg.printf("%d",*(int*)((char*)&(*((char*)&z+1))-1));

[edit]

ok let me re-phrase it:

z = 420

&z = 1310548

*(&(*(&z+1))-1) = 420

(&(*(&z+1))-1)  = 1310548

now I do to corrupt the constant

*((char *)&z+1) = 21;

NOW AFTER CORRUPTING:

z = 420     // NO CHANGE EVEN THOUGH I have corrupted

&z = 1310548

*(&(*(&z+1))-1) = z = 5540    // THE CHANGE

(&(*(&z+1))-1)  = &z = 1310548

WHY?

bakra
  • 387
  • 4
  • 15
  • Perhaps the compiler is optimizing `z` by putting it in a register. Then you do the crazy stuff of accesing the memory of `z` and change it, so the compiler actually reads the memory. It would be interesting to try it without any optimizations. – Starkey Oct 09 '10 at 15:25
  • 7
    I don't think `const` in C means what you think it does. – Williham Totland Oct 09 '10 at 15:27
  • This is some truly obfuscated code. – Rafe Kettler Oct 09 '10 at 15:29
  • C is not exactly well-known for its type safety. – AndersK Oct 09 '10 at 15:44
  • @Anders K. quote: "The type system was added primarily to help the compiler-writer distinguish floats, doubles, and characters from words on the new PDP-11 hardware. This contrasts with languages like Pascal, where the purpose of the type system is to protect the programmer by restricting the valid operations on a data item. With its different philosophy, C rejects strong typing and permits the programmer to make assignments between objects of different types if desired." – bakra Oct 09 '10 at 15:52
  • possible duplicate of [changing const value in C](http://stackoverflow.com/questions/3709548/changing-const-value-in-c) – dmckee --- ex-moderator kitten Oct 09 '10 at 17:11

3 Answers3

6

Congratulations, you lied to the the compiler and it bit you.

Casts tell the compiler that you are intentionally breaking the rules and imply that you know what you are doing. C is happy to allow you to shoot yourself in the proverbial foot when you do this.

msw
  • 42,753
  • 9
  • 87
  • 112
  • because it's not stored in read-only memory.. 'const' only tells compiler that it should'n be changed – fazo Oct 09 '10 at 15:36
6

What you have with int const is in fact not a constant but a const qualified object. So if you play games of changing this object through pointer manipulations this might be possible but delivers undefined behavior.

The only integer constants in C are number tokens, integer character constants such as 'a' and enum constants.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
5

There's not a while lot of mystery here. By using casts to tell the compiler that what you're changing isn't const qualified, you're causing undefined behavior:

6.7.3/5 "Type qualifiers" (C99):

If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.

Some implementations might have placed the variable z in read only memory and you'd either get no apparent change or some sort of access violation.

In any case, undefined behavior means all bets are off - in your case you're able to see the apparent modification of a const value.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760