Consider the following C code fragment running on a 32-bit x86 machine:…
2019
Consider the following C code fragment running on a 32-bit x86 machine:
typedef struct {
union {
unsigned char a;
unsigned short b;
} U;
unsigned char c;
} S;
S B[10];
S *p = &B[4];
S *q = &B[5];
p->U.b = 0x1234;
/* structure S takes 32 bits */If M is the value of q - p and N is the value of ((int)&(p->c)) - ((int)p), then (M, N) is:
- A.
(1, 1)
- B.
(3, 2)
- C.
(1, 2)
- D.
(4, 4)
Attempted by 131 students.
Show answer & explanation
Correct answer: C
Concept. Two independent C rules govern this item. (1) Pointer subtraction between two pointers into the same array yields the difference in ELEMENT count, not bytes: for T *p, *q, q - p equals the number of array elements between them. (2) A member's offset inside a struct is fixed by the LAYOUT of the members that precede it; a union member occupies the size (and alignment) of its largest member, and any tail padding that rounds the whole struct up to its alignment is placed AFTER the last member, so it cannot shift an earlier member's offset.
Application. Apply each rule to S on this 32-bit target where sizeof(S) = 4.
Compute
M = q - p. Herep = &B[4]andq = &B[5]point to consecutive elements of the same arrayB, so the element-count difference isM = 1(the byte gap ofsizeof(S)divided bysizeof(S), which is exactly the rule above).Lay out
S. The unionUholds anunsigned char(1 byte) and anunsigned short(2 bytes); a union's size is its largest member, sosizeof(U) = 2, occupying bytes 0 and 1 at offset 0.Place
c. The next memberunsigned char cfollowsUat the next free byte, socsits at byte offset 2.Compute
N = ((int)&(p->c)) - ((int)p). This expression is exactly the byte offset ofcwithinS, which isN = 2.
Cross-check. The struct is rounded up to sizeof(S) = 4 for alignment; that 1 byte of tail padding sits AFTER c (byte 3). Pointer subtraction counts elements, so the padded sizeof(S) is what makes the stride exactly one element and never alters c's offset of 2. Writing p->U.b = 0x1234 only stores bytes into the union and, with endianness, never moves a member offset. Both rules therefore give (M, N) = (1, 2).
Note. The line S B[10]; is an array declaration, not an assignment, so the absence of = is correct.
A video solution is available for this question — log in and enroll to watch it.