Suppose we declare a variable
int i = 10;
And we have these 2 statements-
printf("%d",i);
printf("%d",*(&i));
These two statements print the same value, i.e. 10
From my understanding of pointers, not just their output is same, but the above two statements mean exactly the same. They are just two different ways of writing the same statement.
However, I came across an interesting code-
#include <stdio.h>
int main(){
const int i = 10;
int* pt1 = &i;
*pt1 = 20;
printf("%d\n", i);
printf("%d\n", *(&i));
return 0;
}
To my surprise, the result is-
10
20
This suggests that i
and *(&i)
don't mean the same if i
is declared with the const
qualifier. Can anyone explain?
CodePudding user response:
The behavior of *pt1 = 20;
is not defined by the C standard, because pt1
has been improperly set to point to the const int i
. C 2018 6.7.3 says:
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…
Because of this, the behavior of the entire program is not defined by the C standard.
In C code with defined behavior, *(&i)
is defined to produce the value of i
. However, in code with behavior not defined by the C standard, the normal rules that would apply to *(&i)
are canceled. It could produce the value that the const i
was initialized to, it could produce the value the program attempted to change i
to, it could produce some other value, it could cause the program to crash, or it could cause other behavior.
CodePudding user response:
Think of what it means to declare something as const
- you're telling the compiler you don't want the value of i
to change, and that it should flag any code that has an expression like i = 20
.
However, you're going behind the compiler's back and trying to change the value of i
indirectly through pt1
. The behavior of this action is undefined - the language standard places no requirements on the compiler or the runtime environment to handle this situation in any particular way. The code is erroneous and you should not expect a meaningful result.
One possible explanation (of many) for this result is that the i
in the first printf
statement was replaced with the constant 10
. After all, you promised that the value of i
would never change, so the compiler is allowed to make that optimization.
But since you take the address of i
, storage must be allocated for it somewhere, and in this case it apparently allocated storage in a writable segment (const
does not mean "put this in read-only memory"), so the update through pt1
was successful. The compiler actually evaluates the expression &(*i)
to retrieve the current value of i
, rather than replacing it with a constant. On a different platform, or in a different program, or in a different build of the same program, you may get a different result.
The moral of this story is "don't do that". Don't attempt to modify a const
object through a non-const
expression.