I'm learning C language, specifically pointers and I have this little question.
How is it possible to save two data in the same memory location on C? Look my code:
#include <stdio.h>
int main()
{
const int y = 2;
int *const ptr_y = &y;
*ptr_y = 4;
//Values
printf("%d\n", y);
printf("%d\n\n", *ptr_y);
//Memory locations
printf("%p\n", &y);
printf("%p\n", ptr_y);
return (0);
}
OUTPUT:
2
4
0x7ffeeb501788
0x7ffeeb501788
OUTPUT I EXPECT:
4
4
0x7ffeeb501788
0x7ffeeb501788
I would like to know how this code works internally.
IMPORTANT: I am aware that the constant pointer is not correctly declared (const int *ptr_y).
CodePudding user response:
First of all, int *const ptr_y = &y;
isn't valid C, so if your compiler made an executable despite this code, all bets of its behavior are off. And in case you got no messages from the compiler, it means that your compiler configuration is non-standard. See What compiler options are recommended for beginners learning C?
Strictly speaking printf("%p\n", &y);
should also be cast to (const void*)&y
.
Where const int y = 2;
stores the value 2 isn't specified by the C standard. It could be in a register, on the stack, in read/write memory labelled "read only" (.rodata
or similar) or it could be stored in true read-only memory like flash, in case of embedded systems.
If you do a write access to that memory location, the behavior isn't defined by the C standard. Undefined behavior = anything could happen, including:
- it could update the memory and next time you read back a
4
. - it could update the memory but the compiler optimizer doesn't generate code to read it back so you still get
2
. - the compiler could ignore to generate code for the write attempt.
- it could be true read-only memory so when you attempt to write to it, nothing happens.
- it could be true read-only memory and protected, so that a write attempt results in a hardware exception or similar.
Overall, it isn't overly meaningful to analyse what exactly happened (symptoms) when you invoke undefined behavior. What's important is to understand why the code contains undefined behavior (root cause).
CodePudding user response:
The code invokes undefined behavior because you cannot change the contents of a const
variable, for that reason the output has no meaning, it can be anything as per the definition of undefined behavior linked above.
You are not saving the data in two different locations, it's the same location.
y
is stored in some (memory) location, that location has an address, ptr_y
is a pointer and it contains that same memory address because you assigned it using address-of
operator &
:
int *const ptr_y = &y;
The above assignment discards the const
qualifier and as such, you are then allowed by the compiler to try and change the value of y
with *ptr_y = 4
, this is still invalid but because of the faulty assignment it becomes possible. You should always respect the const
qualifiers in pointers, if you used:
const int y = 2;
const int* ptr_y = &y;
The compiler would not have let you do it:
*ptr_y = 4;
error: assignment of read-only location '*ptr_y'
With correct code, by dereferencing ptr_y
using *
operator you are accessing the address stored in ptr_y
which incidentally is the address of y
, so it's the same memory address, you are just accessing it in two different ways:
int y = 2; // non const
int *const ptr_y = &y; // constant pointer is allowed
*ptr_y = 4;
//Values
printf("%d\n", y);
printf("%d\n\n", *ptr_y);
//Memory locations
printf("%p\n", (void*)&y); // %p specifier expects void*
printf("%p\n", (void*)ptr_y);
4
4
0x7ffd0f9aee34
0x7ffd0f9aee34