I thought that the &
operator wouldn't work for constants because I thought their invokations are replaced with their values at compile time like with macros and that they're rvalues. I wrote this test and the output suprised me.
#include<stdio.h>
int main(void){
const int a=1;
*(int*)&a=2;
printf("%i%i",a,*&a);
return 0;
}
It outputs 12. I expected it to be 11. Thanks for reaching out.
CodePudding user response:
It outputs 12. I expected it to be 11.
Incorrect expectations.
Casting a pointer to const
data to a pointer to non-const
data is OK - if the resulting pointer is not used to write data.
const int a=1;
(int*)&a; // OK
Attempting to write via a pointer that originated as a pointer to const
data is undefined behavior (UB). Don't code like that. Anything may happen.
*(int*)&a = ... // Not OK
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. C17dr § 6.7.3 7
CodePudding user response:
Check out the significance of the volatile
keyword below.
Two identical functions, except that TrialB has keyword volatile, and TrialA does not.
TrialA
outputs 11
, because the compiler believes that variable a
is const and cannot change.
TrialB
outputs 22
, because despite being declared const
, the variable is also volatile
and therefore needs to be re-examined on every use.
#include<stdio.h>
void TrialA(void)
{
const int a=1;
*(int*)&a=2; // I expected a Warning on this line!
// Along the lines of "incompatible typecast from "const int*" to "int*"
// But surprisingly, I do not see such a warning.
printf("%i%i\n",a,*&a);
}
void TrialB(void)
{
volatile const int a=1;
*(int*)&a=2;
printf("%i%i\n",a,*&a);
}
int main(void){
TrialA();
TrialB();
return 0;
}
Output
Success #stdin #stdout 0s 5536KB
11
22