I was answering a question and made this test program.
#include
int main()
{
volatile const int v = 5;
int * a = &v;
*a =4;
This line:
int * a = &v;
is a constraint violation. The compiler must produce a diagnostic message, and may reject the program. If the compiler produces an executable anyway, then that executable has completely undefined behaviour (i.e. the C Standard no longer covers the program at all).
The constraints violated are that volatile
nor const
may not be implicitly converted away.
To comply with the C standard, the pointer must have its pointed-to type having the same or stronger qualifiers as the object being pointed to, e.g.:
int const volatile *a = &v;
after which you will find that the line *a = 4;
causes a compilation error.
A possible attempt might be:
int *a = (int *)&v;
This line must compile, but then it causes undefined behaviour to read or write via *a
. The undefined behaviour is specified by C11 6.7.3/6 (C99 and C89 had similar text):
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. If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.
It is unsafe because the same behavior cannot be guaranteed for use in other compilers. So your code is compiler-dependent and may even be compiler switch dependent. That's why it's a bad idea.