Quiz Calibration
Attempt the quiz before reading this page. Preserve the original answer, correction and help received. These explanations calibrate retrieval; successful recall alone does not complete the module or its practical evidence gates. For context such as shared schemas, use the question page.
Question 1: Hex Fluency
How many bits fit in two hex digits? How many decimal values does a single byte span as unsigned?
Calibration: Two hex digits encode eight bits. On an eight-bit-byte target, unsigned char spans 0–255. C defines sizeof(char) as 1 but CHAR_BIT is a target property; state that assumption.
Question 2: Two's Complement
Give the 8-bit two's-complement representation of -1 and of -128, and explain why the second is "the negative without a positive."
Calibration: -1 is 0xFF (1111 1111). -128 is 0x80 (1000 0000). +128 would need 9 bits to represent (0 1000 0000), so an int8_t can hold -128 but not +128. This asymmetry is why INT_MIN == -INT_MIN can be true as a bit pattern and why -INT_MIN is undefined behavior as an expression.
Question 3: IEEE 754 Decoding
Decode the 32-bit pattern 0x40490FDB as an IEEE 754 float.
Calibration: Sign = 0. Exponent field = 10000000 = 128, so actual exponent = 128 - 127 = 1. Mantissa = 1.10010010000111111011011_2. Value = 1.5707963... * 2^1 = 3.1415927..., approximately pi.
Question 4: Undefined Behavior on Signed Overflow
Predict the output. What does the C standard say?
int x = INT_MAX;
if (x + 1 < x) puts("overflowed");
else puts("did not");
Calibration: Signed overflow is undefined behavior. There is no required output; execution is not restricted to either listed line. Do not use an observed result as a portability guarantee. Fix by using unsigned or by checking x > INT_MAX - 1 before adding.
Question 5: Pointer Arithmetic Prediction
Predict the output on a typical x86-64 system:
int a[5] = {10, 20, 30, 40, 50};
int *p = a + 2;
printf("%d %d %d\n", *p, p[-1], *(p + 2));
Calibration: 30 20 50. p points to a[2]. p[-1] == *(p - 1) == a[1] == 20. *(p + 2) == a[4] == 50.
Question 6: Type-Scaled Arithmetic
Given double *d; with d == 0x1000, what is the address value of d + 3? What about (char *)d + 3?
Calibration: Only with a valid pointer and sufficient live array/object bounds may these operations be formed. Under an explicit flat-address model with sizeof(double)==8, the illustrated byte offsets are 24 and 3. A numeric address alone does not establish those preconditions or a portable pointer value.
Question 7: Dangerous Cast
Predict the bytes printed on a little-endian machine:
uint32_t x = 0xAABBCCDD;
unsigned char *p = (unsigned char *)&x;
printf("%02x %02x %02x %02x\n", p[0], p[1], p[2], p[3]);
Calibration: dd cc bb aa. Little-endian stores the least-significant byte at the lowest address.
Question 8: Segment Placement
Where do each of these live (stack, heap, .data, .bss, .rodata)?
const char *msg = "hello";
int g_init = 5;
static int g_zero;
int main(void) {
int local;
int *p = malloc(4);
return 0;
}
Calibration: These are common implementation placements, not C language guarantees; optimization may remove objects. msg is commonly in .data (initialized global). "hello" is in .rodata. g_init is in .data. g_zero is in .bss (zero-initialized static). local is on the stack. p may hold a pointer to allocated storage if malloc succeeds; p itself is commonly in a stack slot or register. Four allocated bytes do not universally guarantee room for an int.
Question 9: Stack-Frame Tracing
Briefly describe what the x86-64 function prologue push rbp; mov rbp, rsp; sub rsp, 32 does in words.
Calibration: It saves the caller's frame-pointer register on the stack, sets the current frame pointer to the current stack pointer, and then reserves 32 bytes of local-variable space by decreasing the stack pointer.
Question 10: Heap Discipline
Is there a bug in this code, and if so, what kind?
char *p = malloc(32);
if (p != NULL) strcpy(p, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJ");
free(p);
Calibration: Yes: a heap-buffer overflow. strcpy writes 37 bytes (including \0) into a 32-byte allocation. ASan catches this immediately.
Question 11: Use-After-Free
Which line is the use-after-free?
char *s = malloc(16);
strcpy(s, "hello");
free(s);
printf("%s\n", s);
Calibration: The printf on line 4 dereferences s after s has been freed. Fix by not reading s after free, or by setting s = NULL; immediately after free and checking before use.
Question 12: Struct Layout Prediction
On x86-64 with default alignment, what is sizeof(struct S)?
struct S { char c; int i; char d; };
Calibration: 12. c at offset 0 (1 byte), 3 bytes padding, i at offset 4 (4 bytes), d at offset 8 (1 byte), 3 bytes trailing padding so the struct aligns to 4 on array next element. Total = 12.
Question 13: Endianness on the Wire
On a little-endian host, uint32_t x = 0x01020304; write(fd, &x, 4);. Another machine reads the 4 bytes into its own uint32_t y with read. If that machine is big-endian, what does it see in y?
Calibration: It sees 0x04030201. The wire bytes were 04 03 02 01 (low address first, little-endian order). The big-endian reader treats the first byte as the most significant, giving 0x04030201. The fix is to use htonl / ntohl or explicit byte order on both ends.
Question 14: Alignment vs Packing
What is the risk of __attribute__((packed)) on a struct with an int field followed by a double field?
Calibration: The double loses its natural 8-byte alignment. On architectures that trap on misaligned accesses, reading or writing that field can crash (SIGBUS) or be served by a very slow software-emulated path. Even on x86-64, sanitizers and some compiler passes flag unaligned access as undefined behavior.
Question 15: Tricky Cast and Alignment Prediction
Predict whether this compiles clean and what it prints on a typical Linux x86-64 system:
char buf[5] = { 0x78, 0x56, 0x34, 0x12, 0x00 };
uint32_t v;
memcpy(&v, buf, 4);
printf("0x%08x\n", v);
Calibration: Prints 0x12345678. memcpy is the safe way to reinterpret bytes regardless of alignment. Note that uint32_t *p = (uint32_t *)buf; would be undefined behavior because buf may not satisfy uint32_t alignment and because of strict-aliasing rules. memcpy is the portable fix.
Prior Module Question 1 (S1 Module 3: Probability)
What does linearity of expectation say, and why does it not require independence?
Calibration: E[X + Y] = E[X] + E[Y] for any random variables X and Y. Expectation is a linear functional, so the identity follows from the definition of expectation regardless of whether X and Y are independent.
Prior Module Question 2 (S2 Module 1: Algorithm Analysis)
Solve T(n) = 2 T(n/2) + n using the Master Theorem.
Calibration: a = 2, b = 2, n^(log_b a) = n, and f(n) = Theta(n). Case 2 applies, giving T(n) = Theta(n log n).
Prior Module Question 3 (S3 Module 2: Software Design)
What is the core idea of the Single Responsibility Principle in one sentence?
Calibration: A module should have exactly one reason to change, which usually means it should be responsible for one stakeholder-facing concern.
Prior Module Question 4 (S4 Module 1: C Programming Fundamentals)
What does static mean for a file-scope variable versus a function-scope variable in C?
Calibration: At file scope, static limits the identifier's linkage to this translation unit (other files cannot see it). At function scope, static gives the local variable static storage duration (lifetime equals the program, not the call) while keeping its identifier scoped to the function.
Prior Module Question 5 (S1 Module 1: Proof Techniques)
Prove by induction that sum_{i=1}^n i = n(n+1)/2.
Calibration: Base n=1: 1 = 1*2/2. Inductive step: assume sum_{i=1}^k i = k(k+1)/2. Then sum_{i=1}^{k+1} i = k(k+1)/2 + (k+1) = (k+1)(k+2)/2, which is the claim for k+1. QED.