Project 1: Compiler Behavior Laboratory

A test harness that demonstrates implementation-defined, unspecified, and undefined behavior across compilers and optimization levels.

Quick Reference

Attribute Value
Primary Language C
Alternative Languages None (this is about C compilers)
Difficulty Level 2 - Intermediate
Time Estimate See main guide
Knowledge Area Compilers, Language Semantics
Tooling GCC, Clang, MSVC
Prerequisites See main guide

What You Will Build

A test harness that demonstrates implementation-defined, unspecified, and undefined behavior across compilers and optimization levels.

Why It Matters

This project builds core skills that appear repeatedly in real-world systems and tooling.

Core Challenges

  • Observing optimization effects → Maps to understanding how UB enables compiler transforms
  • Cross-compiler differences → Maps to portability concerns
  • Documenting behavior categories → Maps to reading the C standard

Key Concepts

  • Map the project to core concepts before you code.

Real-World Outcome

# 1. Compile same code with different compilers
$ gcc -std=c23 -O0 -o test_gcc_o0 behavior_test.c
$ gcc -std=c23 -O3 -o test_gcc_o3 behavior_test.c
$ clang -std=c23 -O0 -o test_clang_o0 behavior_test.c
$ clang -std=c23 -O3 -o test_clang_o3 behavior_test.c

# 2. Run and compare signed overflow behavior
$ ./test_gcc_o0
Test: Signed overflow (INT_MAX + 1)
Result: -2147483648  (wrapped around - common at -O0)

$ ./test_gcc_o3
Test: Signed overflow (INT_MAX + 1)
Result: 2147483647   (optimized away - compiler assumed no overflow!)

# 3. Compare implementation-defined behavior
$ ./test_gcc_o0 impl_defined
Right shift of -1: -1  (arithmetic shift - sign extended)
sizeof(int): 4

$ ./test_clang_o0 impl_defined
Right shift of -1: -1  (same on this platform)
sizeof(int): 4

# 4. Generate comparison report
$ ./run_all_tests.sh > behavior_report.txt
$ cat behavior_report.txt
=== BEHAVIOR COMPARISON REPORT ===
Test Case              | GCC -O0  | GCC -O3  | Clang -O0 | Clang -O3
--------------------   | -------- | -------- | --------- | ---------
signed_overflow        | -2^31    | 2^31-1   | -2^31     | <crash>
null_ptr_check_elim    | checked  | skipped  | checked   | skipped
uninitialized_read     | 0        | 42       | garbage   | 0
...

Implementation Guide

  1. Reproduce the simplest happy-path scenario.
  2. Build the smallest working version of the core feature.
  3. Add input validation and error handling.
  4. Add instrumentation/logging to confirm behavior.
  5. Refactor into clean modules with tests.

Milestones

  • Milestone 1: Minimal working program that runs end-to-end.
  • Milestone 2: Correct outputs for typical inputs.
  • Milestone 3: Robust handling of edge cases.
  • Milestone 4: Clean structure and documented usage.

Validation Checklist

  • Output matches the real-world outcome example
  • Handles invalid inputs safely
  • Provides clear errors and exit codes
  • Repeatable results across runs

References

  • Main guide: PROFESSIONAL_C_PROGRAMMING_MASTERY.md
  • Effective C, 2nd Edition by Robert C. Seacord