It's from a elementary question from the very beginning of MIT6.s081, Why does the fifth printf's result is:
5: a[0] = 200, a[1] = 128144, a[2] = 256, a[3] = 302
I really can't imagine how 128144 comes!
Here is the code:
#include <stdio.h>
#include <stdlib.h>
void f(void)
{
int a[4];
int *b = malloc(16);
int *c;
int i;
printf("1: a = %p, b = %p, c = %p\n", a, b, c);
c = a;
for (i = 0; i < 4; i )
a[i] = 100 i;
c[0] = 200;
printf("2: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c[1] = 300;
*(c 2) = 301;
c[3] = 302;
printf("3: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c = c 1;
*c = 400;
printf("4: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c = (int *)((char *)c 1);
*c = 500;
printf("5: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
b = (int *)a 1;
c = (int *)((char *)a 1);
printf("6: a = %p, b = %p, c = %p\n", a, b, c);
}
int main(int ac, char **av)
{
f();
return 0;
}
CodePudding user response:
A standard integer is 4 bytes in width, meaning that, in memory, your 500 will look like this (assuming Big endian): 0x00 0x00 0x01 0xF4
.
If you do c 1
, with c
being an int *
you are actually moving the pointer by these four bytes.
By casting c
to a char *
, you change the step width of the pointer to 1
, meaning that it will now point to this location: 0x00 0x00 0x01 0xF4
By writing your 500 to that value, the same four bytes will now look like this: 0x00 0x00 0x00 0x01
(the remaining 0xF4 will be written to the next integer).
I am now assuming that your machine is little endian, meaning the bytes are 'reversed'.
0x90 0xF4 0x01 0x00
The 0x90 is leftover from the assignment of 400 in the previous iteration and by putting them all together, you get 0x01f490 or 128144.
CodePudding user response:
After 4: a[0] = 200, a[1] = 400, a[2] = 301, a[3] = 302
The binary value of the array pointed by a
and c
is as following:
a
c
C8 00 00 00 | 90 01 00 00 | 2D 01 00 00 | 2E 01 00 00
After c = (int *) ((char *) c 1);
a
| c
| |
C8 00 00 00 | 90 01 00 00 | 2D 01 00 00 | 2E 01 00 00
After *c = 500; // 500 = 0x000001F4
a
| c
| |
C8 00 00 00 | 90 F4 01 00 | 00 01 00 00 | 2E 01 00 00
So a[1] = 0x0001F490; a[2] = 0x00000100;
And 0x0001F490 = 128144, 0x00000100 = 256
.