A strong answer
In C, pointer arithmetic is automatically scaled by the size of the pointed-to type (sizeof(*p)). Adding an integer n to a pointer T *p computes the byte address:
byte_address(p + n) = byte_address(p) + n * sizeof(T)
Therefore, if int *p holds address 0x1000 and sizeof(int) is 4, then p + 3 advances by 3 * 4 = 12 bytes (0xC in hex) and evaluates to address 0x100C—not 0x1003! Conversely, subtracting two pointers targeting the same array (q - p) divides the byte difference by sizeof(T) and returns a signed ptrdiff_t count of elements between them: (int *)0x1010 - (int *)0x1000 is 16 / 4 = 4 elements.
When writing systems code such as a custom allocator, packet parser, or serialization buffer where you genuinely want to advance by an exact number of bytes, you must cast the pointer to a 1-byte character type—Specifically uint8_t *, unsigned char *, or char *—where sizeof(*p) == 1, so (uint8_t *)p + 3 lands at 0x1003.
What the interviewer is listening for
- Immediately answers
0x100C(0x1000 + 3 * 4) and states the general scaling rulen * sizeof(*p). - Knows that pointer subtraction
q - pyields the element count (ptrdiff_t) and is only defined when both pointers point into (or one past the end of) the same array object. - Uses
uint8_t *orunsigned char *for byte-level pointer stepping.
Common mistakes
- Double-scaling pointer offsets by writing
int *next = p + 3 * sizeof(int);, which actually advances by3 * 4 * 4 = 48bytes instead of 12 bytes! - Attempting pointer arithmetic directly on
void *in strict ISO C (standard C forbidsvoid *arithmetic becausevoidhas no size, though GCC allows it as a 1-byte extension). - Forming a pointer outside
[base, base + len](onlybase + len, the "one-past-the-end" pointer, is legal to form without dereferencing;base - 1is undefined behavior).