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 */

Assume the conventional 32-bit x86 ILP32 ABI: unsigned short is 2 bytes with 2-byte alignment, pointers and int are 32 bits, pointer-to-int conversion preserves the numerical address, and the displayed integer subtraction does not overflow.

If M is the value of q - p and N is the value of ((int)&(p->c)) - ((int)p), then (M, N) is:

  1. A.

    (1, 1)

  2. B.

    (3, 2)

  3. C.

    (1, 2)

  4. D.

    (4, 4)

Attempted by 148 students.

Show answer & explanation

Correct answer: C

Concept. Two independent C rules govern this item.

  • Pointer subtraction between two pointers into the same array yields the difference in element count, not bytes.

  • A member offset is determined by the layout, size, and alignment of preceding members; tail padding after the last member cannot shift an earlier member.

Application. Apply each rule to S on this 32-bit target where sizeof(S) = 4. The explicit ILP32 assumptions also make the two pointer-to-int conversions preserve their numerical addresses for this subtraction.

  1. Compute M = q - p. Here p = &B[4] and q = &B[5] point to consecutive elements of the same array B, so the element-count difference is M = 1 (the byte gap of sizeof(S) divided by sizeof(S), which is exactly the rule above).

  2. Lay out S. The union U holds an unsigned char (1 byte) and an unsigned short (2 bytes); a union's size is its largest member, so sizeof(U) = 2, occupying bytes 0 and 1 at offset 0.

  3. Place c. The next member unsigned char c follows U at the next free byte, so c sits at byte offset 2.

  4. Compute N = ((int)&(p->c)) - ((int)p). Under the stated address-preserving ILP32 assumptions, subtracting the converted numerical addresses yields the byte offset of c within S, which is N = 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.

Explore the full course: Nta Ugc Net Paper 2

Loading lesson…