Look at the following C code:
#include <stdio.h>
int main(int argc, char* argv[])
{
char a = 0, b = 0;
int* p = (int*)&b;
*p = 258;
//printf("%d %d\n%p %p\n", a, b, &a, &b);
printf("%p %p\n%d %d\n", &a, &b, a, b);
//printf("%p %p\n", &a, &b);
//printf("hd\n");
//printf("%p %p\n", &a, &b);
}
The above output:
1 2
0061FF1B 0061FF1A
#include <stdio.h>
int main(int argc, char* argv[])
{
char a = 0, b = 0;
int* p = (int*)&b;
*p = 258;
printf("%d %d\n", a, b);
//printf("%p %p\n", &a, &b);
}
The above output:
0 2
Two pieces of code that comment one line of output will result in a different output on the first line. Why?
CodePudding user response:
EDIT: Your code is an example of an Undefined Behaviour, but I will try to explain in detail why my computer outputs the same as your second output.
The following code in my computer gives your second output, which is what makes the most sense.
#include <stdio.h>
int main(int argc, char* argv[])
{
char a = 0, b = 0;
int* p = (int*)&b;
*p = 258;
//printf("%d %d\n%p %p\n", a, b, &a, &b);
printf("%p %p\n%d %d\n", &a, &b, a, b);
//printf("%p %p\n", &a, &b);
//printf("hd\n");
//printf("%p %p\n", &a, &b);
}
Outputs:
&a=0x7ffe2c4f7bde &b=0x7ffe2c4f7bdf
a=0 b=2
Assuming big endianness, bytes are read from left to right in ascending value order. If you declared first a and then b, then the memory of a is located at the right of b (depending on the compiler it might be reversed, but I will try to explain my computers behaviour), diagramatically:
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
- - - - - - - - - - - - - - - -
| b | a |
- - - - - - - - - - - - - - - -
if you cast the pointer to b as an int, then the compiler will think you have 4 bytes instead of one at the left of a, and will write to it. 258 in binary is 0b100000010, so only the last 8 bits of this fall into the char range that b reads, which would be 0000 0010, which is 2. This is why a stays zero. A cool way to test this is declaring another char c after b, and checking how after executing the same program, c is 1 because it is located at the inmediate left of b and *p = 258 would have written the first bit of c to 1. Here's what I mean:
#include <stdio.h>
int main(int argc, char* argv[])
{
char a = 0, b = 0, c = 0;
int* p = (int*)&b;
*p = 258;
printf("&a=%p &b=%p\n &c=%p a=%d b=%d c=%d\n", &a, &b, &c, a, b, c);
}
Outputs:
&a=0x7ffc6ce4943d &b=0x7ffc6ce4943e
&c=0x7ffc6ce4943f a=0 b=2 c=1
CodePudding user response:
The problem is that you're typecasting a char*
to an int*
and then dereferencing p
which leads to undefined behavior.
Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior. The program may just crash.
So the output that you're seeing(maybe seeing) is a result of undefined behavior. And as i said don't rely on the output of a program that has UB. The program may just crash.
So the first step to make the program correct would be to remove UB. Then and only then you can start reasoning about the output of the program.
1For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program.