As others mentioned, the cast removes the 'constness' of the destination as far as the expression is concerned. When you use a cast the compiler treats the expression according to the cast - as long as the cast itself it valid (and C-style casts are pretty much the big hammer). This is why you don't get an error or warning. You're essentially telling the compiler, "be quiet, I know what I'm doing, this is how you should treat things". In fact, casts are probably the #1 way for programmers to get the compiler to stop issuing warnings.
Your assignment expression may or may not be undefined behavior. It is permitted to cast away constness if the object actually pointed to is not const.
However, if the object pointed to is const, then you have undefined behavior.
void TestFunc(const void * const Var1, const float Var2)
{
*(float*)Var1 = Var2;
}
int
main(void)
{
float x = 1.0;
const float y = 2.0;
TestFunc( &x, -1.0); // well defined (if not particularly great style)
TestFunc( &y, -2.0); // undefined behavior
return 0;
}
You're treading dangerous waters...
In general (I'm sure there are exceptions), casting so that expressions treat objects as they really are is supported, well-defined behavior in C/C++.
This particular behavior is covered in the standards mostly by statements that modifying a const object through a cast (or something) that removes the const qualifier is undefined. The inference is that doing the same for a non-const object is not undefined. An example given in the C++ standard makes this clear.
C90 6.5.3 - Type Qualifiers (C99 6.7.3):
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.
C++ 7.1.5.1 The cv-qualifiers
A pointer or reference to a cv-qualified type need not actually point or refer to a cv-qualified object, but it is treated as if it does; a const-qualified access path cannot be used to modify an object even if the object referenced is a non-const object and can be modified through some other access path. [Note: cv-qualifiers are
supported by the type system so that they cannot be subverted without casting (5.2.11). ]
Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const
object during its lifetime (3.8) results in undefined behavior.
...
[Example:
...
int i = 2; //not cv-qualified
const int* cip; //pointer to const int
cip = &i; //OK: cv-qualified access path to unqualified
*cip = 4; //ill-formed: attempt to modify through ptr to const
int* ip;
ip = const_cast<int*>(cip); //cast needed to convert const int*to int*
*ip = 4; //defined: *ip points to i, a non-const object
const int* ciq = new const int (3); //initialized as required
int* iq = const_cast<int*>(ciq); //cast required
*iq = 4; //undefined: modifies a const object
const char*
is, as you said, a pointer to a char, where you can't change the value of the char (at least not through the pointer (without casting the constness away)).
char* const
is a pointer to a char, where you can change the char, but you can't make the pointer point to a different char.
const char* const
is a constant pointer to a constant char, i.e. you can change neither where the pointer points nor the value of the pointee.
Best Answer
const
actually doesn't mean "constant". Something that's "constant" in C has a value that's determined at compile time; a literal42
is an example. Theconst
keyword really means read-only. Consider, for example:The value of
r
is not determined until program execution time, but theconst
keyword means that you're not permitted to modifyr
after it's been initialized.In your code:
the assignment
ptr = &x;
is a constraint violation, meaning that a conforming compiler is required to complain about it; you can't legally assign aconst int*
(pointer to const int) value to a non-constint*
object. If the compiler generates an executable (which it needn't do; it could just reject it), then the behavior is not defined by the C standard.For example, the generated code might actually store the value
2
inx
-- but then a later reference tox
might yield the value1
, because the compiler knows thatx
can't have been modified after its initialization. And it knows that because you told it so, by definingx
asconst
. If you lie to the compiler, the consequences can be arbitrarily bad.Actually, the worst thing that can happen is that the program behaves as you expect it to; that means you have a bug that's very difficult to detect. (But the diagnostic you should have gotten will have been a large clue.)