ABCDEFGHIJKLMNOPQRSTUVWXYZ*; ^ ^ ^ s x y |
After strcpy(x, "01234567"), it will look as follows:
AB01234567*LMNOPQRSTUVWXYZ*; ^ ^ ^ s x y |
And then after strcat(y, "abcde"), it will look as follows:
AB01234567abcde*QRSTUVWXYZ*; ^ ^ ^ ^ s x y x+15 |
So, here are the answers:
01234567890123456789* ^ ^ s s+12 |
After memcpy(s+12, argv[1], strlen(argv[1])), it will look as follows. Note, the memcpy() command doesn't copy the null character, because it only copies three bytes:
012345678901abc56789* ^ ^ s s+12 |
So, line 2 is "012345678901abc56789".
Let's draw ip+1 and ip+2 in the picture. Because ip points to integers, ip+1 is four bytes beyond s and ip:
012345678901abc56789* ^ ^ ^ s ip+1 ip+2 |
The memcpy() command also copies three bytes, and it now includes the null character:
0123AB*78901abc56789* ^ ^ ^ s ip+1 ip+2 |
So, printing s gets us "0123AB". When we print ip[2] in hex, it will print the hex corresponding to the characters '1', '0', '9', and '8' in that order, because integers are interpreted in little endian. '0' is 0x30, so the integer printed will be 0x31303938. Here are the answers:
ABCDEFGHABCDEFGHQRSTUVWXYZ*; ^ ^ s x+1 |
So the first printf() prints "ABCDEFGHABCDEFGHQRSTUVWXYZ".
The strcpy() doesn't do anything, but I wanted to make sure that the first 7 bytes equal "ABCDEFG" even if you messed up the first line. j is set to equal whatever "ABCD" equals (yes, I can calculate it, but it's really easier not to calculate it). When I increment x->c1, that sets the 'E' to an 'F', and incrementing x->c1, sets the 'F' to an 'G'. Incrementing x->i sets the 'A' to a 'B'. Here's memory:
BBCDFGG*ABCDEFGHQRSTUVWXYZ*; ^ s |
So it prints out "BBCDFGG". Now, incrementing x->i by (1 << 8) increments the second 'B' byte by one. Similarly, incrementing x->i by (1 << 17) increments the 'C' byte by two. So, S is now "BCEDFGG".
Finally, we incremented i by (1 + (1 << 8) + (1 << 17)). In hexadecimal, that is 0x20101. So that is the last value printed out. Here's the answer:
Bit-shifting j left by 2 turns (1111 0000 1111 0000 1111) into (11 1100 0011 1100 0011 1100). So the answer is 0x3c3c3c.
Doing the binary AND with i and j zeros out the digits where j is zero: 0x10305.
Doing the binary AND with i and j copies the i digits where j is zero, and otherwise sets them to 0xf: 0xf2f4f.
Doing the binary XOR with i and j again copies the i digits where j is zero, and negates the digits where j is 0xf. To negate, simply subtract from 15. So the answer is 0xe2c4a.
When you bit shift j by four, that's one digit to the left. So you are doing the OR of 0xf0f0f with 0xf0f0f0. The answer is 0xffffff.
Finally, bit-shifting i left by 12 digits adds three zeros to the hex: 0x12345000. Oring that with j gets you 0x123f5f0f.
So, here are the answers:
i=0 x+i=0x100130 x[i]=0x10014c i=1 x+i=0x100134 x[i]=0x100130 i=2 x+i=0x100138 x[i]=0x100130 i=3 x+i=0x10013c x[i]=0x100150Pointers are four bytes, so the address of j+i will equal the address of x+i. However, now we treat the value as a pointer and look it up. For example, j is 0x100130. *j is 0x10014c and **j is 0x0x100138.
i=0 j+i=0x100130 *j[i]=0x100138 i=1 j+i=0x100134 *j[i]=0x10014c i=2 j+i=0x100138 *j[i]=0x10014c i=3 j+i=0x10013c *j[i]=0x100130The next loops do more indirection. Here are the pointers and values:
i | X | j = *X | *j | **j |
0 | 0x100130 | 0x10014c | 0x100138 | 0x100130 |
1 | 0x10014c | 0x100138 | 0x100130 | 0x10014c |
2 | 0x100138 | 0x100130 | 0x10014c | 0x100138 |
3 | 0x100130 | 0x10014c | 0x100138 | 0x100130 |
So, here's the answer:
i=0 j=0x10014c **j=0x100130 i=1 j=0x100138 **j=0x10014c i=2 j=0x100130 **j=0x100138 i=3 j=0x10014c **j=0x100130
0x4d5750 0x4d5761 'a' |'W' |'M' |'\0' 0x4d5754 0x4d6264 'd' |'b' |'M' |'\0' 0x4d5758 0x635764 'd' |'W' |'c' |'\0' 0x4d575c 0x644d5754 'T' |'W' |'M' |'d' 0x4d5760 0x4d576c 'l' |'W' |'M' |'\0'So, when you print the four strings, you get:
i=0 y+4*i=aWM i=1 y+4*i=dbM i=2 y+4*i=dWc i=3 y+4*i=TWMdlWM |