CS 2505 OQ03: Pointers Q A Reason ------------------------------------------------------------------------------------- 1 8 P == Q is comparing the values of P and Q, so: 1 is false; P and Q are different variables, so they are at different addresses. 2 is true; if P and Q are equal, they store the same address, and so they point to the same thing, and obviously that thing has the same value as itself. 3 is true; if P and Q are equal, their difference is 0, which is the value of NULL. 2 5 *Q == *R is comparing the values of the things that Q and R point to, so: 1 might be true or not; depends on whether Q and R point to the same thing. 2 is false; Q and R are different variables. 3 might be true or not; just as 1. 3 8 &*P means the address of the target of P, which just the value of P; so this is just a different way of writing question 1, except that P and R are involved. For Q4-Q7, note that the pointers have the following values initially: P: 0xFFA144C8 Q: 0xFFA144C4 4 8 *P = *Q assigns the value of the target of Q to the target of P; in other words this assigns the value of Y to X, so X is now 20; P and Q are unchanged. 5 5 Y = *P + 10 assigns Y the value X + 10, which would be 20 (so no change to Y). *Q += 20 adds 20 to the target of Q, which is Y, making Y equal 40. 6 1 Aside from experimenting with this one, if you looked up the C precedence rules, the dereference has lower precedence than the suffix ++, so Q is incremented, then dereferenced, and similarly for P. *(Q)++ increments Q, so Q becomes equal to &X. *(P)-- decrements P, so P becomes equal to &Y. BTW, if you wrote (*Q)++ instead, then the value of Q's target would be incremented. 7 7 Q++ increments Q, so Q now points to X, and Q == 0xFFA144C8. P-- decrements P, so P now points to Y, and P == 0xFFA144C4. The next two statements increment Q and decrement P again, leaving their values 0xFFA144CC and 0xFFA14C0. 8 5 P points to A[0], so P + k would point to A[k]... Note the loop test is P <= Limit; because of the '=', we want Limit to be the address of the last element in the array, A[Size - 1]. 1 is correct because this would make Limit point to A[Size], which is just past the end of the array. 2 will not work, since P + Size - 1 points to A[Size - 1]; the loop would not process the last element. 3 is correct for the same reason 1 is correct. 4 will not work, for the same reason as 2. 9 5 P points to A[0], so P + k would point to A[k], so we want to process A[0] through A[Size - 1], sequentially. 1 and 2 work because each steps P forward by 1 slot. 3 and 4 fail because each steps P forward by 4 slots. 10 5 (p + 4) is the address of the fifth byte of the memory block, 0x66. Step forward 4 positions from the initial byte. 11 6 (p + 16) points to the byte 0x08 (beginning of the second "row"). 12 6 (p + 0xA) points to the byte 0x61 (first "row"). (uint16_t*)(p + 0xA) yields a pointer with a 2-byte target; dereferencing it yields a 2-byte value, the bytes being "61 67". But if we interpret that as an integer, it's stored in little-endian order, and so the value is 0x6761, not 0x6167. 13 1 (uint32_t*)(p) casts p to a pointer with a four-byte target. Dereferencing that yields a four-byte value: 0x6F050057. 14 2 *p yields the 1-byte value 0x57. Casting that to a uint32_t yields a 4-byte representation of the same value, so it just gets padded with leading zeros. 15 5 This is the same as 14 except that we start with a pointer to the byte 0x73. *(uint32_t*)(p+ 8) yields the four-byte value at that address: 0x67616873 16 2 The only occurrence of 0x00DB6573 in the data segment 4 bytes after the target of p, which would be at (p + 4). To get a 4-byte value, we need to cast the pointer (p + 4) to be a uint32_t* before dereferencing. 1 is wrong; it would get the 1-byte value 0x73 and cast it to 32 bits. 3 is wrong; it would get the 1-byte value 0x08 and cast it to 32 bits. 17 1 *(uint16_t*)(p) yields a 2-byte integer beginning at p. (uint16_t)(*p) yields a 1-byte value, 0x08, and widens it to 0x0008. However, answer 3 is interesting: *p yields the one-byte value 0x08. uint16(*p) casts that to the value 0x0008. *(p+1) yields the one-byte value 0x6E. (unit16_t)(*(p+1)) casts that to the value 0x006E. The shift yields the value 0x06E0. But, the addition yields 0x0008 + 0x06E0 != 0x6E08. With an 8-bit shift, it would have worked... 18 1 *p yields 0x08, so (*p) + 4 yields 0x08 + 0x04 == 0x0C. *(p + 4) yields 0x73. (*p) >> 4 yields 0x08 >> 4 == 0x0. 19 2,8 0xAF occurs two bytes before the target of p, so *(p - 2) yields that. Now, 0xAF == 0x00AF, so answer 2 makes sense. However, *(p - 2) does yield a 1-byte value, not a 2-byte value. A better answer would have been: (uint16_t)( *(p - 2) ). 20 7 0x08 occurs at p, at p - 8 and at p + 8, as well as a p. Note the addresses: p == 0x0028CCD8 p - 8 == 0x0028CCD0 p + 8 == 0x0028CCE0 21 5 Remember that the high bit indicates the sign of the value, so in 1) and 2) both values are positive, and in 3) and 4), both values are negative. 0x704F < 0x7053, since 4F < 53, so 1) is true and 2) is false. 0xAFFF represents -0x5001 and 0xB00D represents -0x4003, and so 0xAFFF < 0xB00D, so 3) is true and 4) is false. 22 5 This is different from the previous question because the values are unsigned (nonnegative). So, from the analysis above, it's clear that 1) is true (same question, really), and that 3) is true (A < B). 23 7 0xF347 --> 1111 0011 0100 0111, so flipping bits and adding 1 yields: --> 0000 1100 1011 1001, which is 0x0CB9, so 2) is true. ~0xF347 is 0000 1100 1011 1000, which is 0x0CB8, so 3) is true 24 9 0x704F: 0111 0000 0100 1111 0x7053: 0111 0000 0101 0011 --> their AND is 0111 0000 0100 0011 --> 0x7043, so 3) is true And for the OR, looking at the bitwise representations above: 0111 0000 0101 1111 --> 0x705F, so 6) is true 25 5 Using the bitwise representations from above: 0111 0000 0100 1111 0111 0000 0101 0011 XOR 0000 0000 0001 1100 --> 0x001C, so 1) is true And: 0x704F: 0111 0000 0100 1111 0x704F: 0111 0000 0100 1111 XOR: 0000 0000 0000 0000, so 3) is true Note that A xor A is always 0.