3

Why can you kind of cheat compiler this way:

const int a = 5; *((int*)&a)=5; // VC/armcc does not complain 

when above is "abridged" equivalent of this:

const int *ptr2const = &a; int *ptr = ptr2const; // as expected error is raised here *ptr = 5; 
1
  • 2
    The second version of your code is not 'equivalent' to the first. The C language requires explicit casts to remove qualifiers from pointer types; a correct compiler can (and should) reject the second piece of code as you've written it. Sadly most just issue a warning. Commented Nov 16, 2010 at 23:16

7 Answers 7

10

Casting is your way of telling the compiler "I know what I'm doing", so it doesn't complain. Unfortunately, in this instance, you will invoke undefined behaviour.

Sign up to request clarification or add additional context in comments.

1 Comment

Or, "unfortunately, in this instance, you don't know what you're doing" ;-)
7

C-style casts allow you to cast away constness like in your example. In C++, you would normally use the new style casts such as static_cast<>, which don't allow you to cast away constness. Only const_cast<> allows you to do that.

4 Comments

..C compiler does not prevent you from writing to const variables and that const (apart from some obvious situations) does not help you much :-D
@Artur: Sure it does. When you attempt to modify a constant variable, you get a compiler error. It doesn't get more straightforward than that. What it does let you do is explicitly cast types, so you can do stupid things all day long. But don't misplace that stupidity and say the C compiler or const isn't helpful; it's on you.
@GMan - I agree - I do not write such code on daily basis but today I've seen void pointer to const volatile as an argument to a routine and started to play with it and it turned out (was not really expecting that) that theoretically you can do anything with a memory area pointed to by that pointer and adding const will not make compiler to even warn you. That is why I wrote that apart from some obvious situations (like dereferencing and assignment) your compiler will not try to do its best to stop you from writing to const area/variable. I did not expect compiler to just "ignore" it.
@Artur: Right. Const is just a compile-time type annotation that is way less useful and flexible than type annotations present in many other languages. It's more or less useless, though plenty of people still use it as a sort of code-documentation thing.
4

To be equivalent, the 2nd line of the 2nd snippet

int *ptr = ptr2const; // as expected error is raised here 

should be written as

int *ptr = (int *)ptr2const; 

Comments

2

Because C throws away a lot of type safety in order to gain a lot of speed instead. It cannot prevent you from doing incorrect things. It may try to warn you that you are doing incorrect things, but you can always work around the compiler if that is your goal.

Comments

2

Convert your constant to a string and you may find that while the compiler will let you cast away the const (inadvisable though it may be), the linker may put the constant string in read-only memory leading to a runtime crash.

Comments

1

C-style casts, such as (int*) are equivalent to C++ const_cast in their ability to cast away constness, so you can side-step const-correctness by using them, although such use is unrecommended (can lead to undefined behaviour).

int main() { const int x = 1; (int&)x = 2; std::cout << x << std::endl; } 

On my system, the above writes 1 to stdout. You might experience different behaviour.

On the other hand...

void foo(const int& x) { (int&)x = 2; } int main() { int x = 1; foo(x); std::cout << x << std::endl; } 

This writes 2 for me. The difference is that the const used in foo is const as a type qualifier, while in the main in the first example it was used as a storage class. It's not always easy to see whether a variable was declared with const as a storage class, so it's best not to rely on a const_cast or C-style cast to cast away const.

It's best just to use static_cast in most situations as this will warn you at compile time of any suspect behaviour in the form of a compile error.

1 Comment

They're not equivalent. This specific instance gives the same result as a const_cast. The reason for C++ having different cast syntaxes for casts of different nature is precisely to avoid accidentally invoking an invalid cast like this.
0

This only "works" because the variable is local, and implementations have no way to enforce const-ness on a local (automatic) variable in general (at least not if the address of the variable is ever taken). But as far as the language specification is concerned, this is in the realm of undefined behavior.

If you try this on a global/static variable, you'll quickly find that most implementations can and do enforce const by putting the variable in read-only memory which can be shared between multiple instances of your program.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.