A situation the standard imposes NO requirements on; the entire program's behavior becomes void — anything may happen.
UB vs unspecified vs implementation-defined?
UB = no requirements at all; unspecified = one of several allowed outcomes, undocumented; implementation-defined = allowed-outcome that MUST be documented.
Is signed integer overflow UB?
Yes — INT_MAX + 1 is undefined.
Is unsigned integer overflow UB?
No — it is defined to wrap modulo 2^n.
Why does the compiler exploit UB?
It assumes UB never happens, which licenses aggressive optimizations (e.g. deleting "impossible" checks).
Why is i = i++; UB?
i is modified twice without an intervening sequence point ordering the two modifications.
Is dereferencing a one-past-the-end pointer allowed?
No — forming the pointer is legal, dereferencing it is UB.
Why is "it ran fine" not proof code is UB-free?
UB can appear to work, then break with a new compiler, flag, or input; it's nondeterministic by spec.
Two compiler tools to catch UB?
-fsanitize=undefined (UBSan) and -fsanitize=address (ASan), plus -Wall -Wextra.
Correct way to check signed overflow before adding 100?
if (x > INT_MAX - 100) ... — compare in the non-overflowing domain.
Is modifying a string literal UB?
Yes — char *s="hi"; s[0]='H'; is undefined.
What is a dangling pointer?
A pointer to storage whose lifetime has ended (freed memory or a returned local).
Recall Feynman: explain to a 12-year-old
Imagine a board game with a rulebook. Most rules say exactly what to do. But there's one scary rule: "If you ever do THIS forbidden move, the rulebook stops applying and the game can do literally anything — give you a million points, flip the board, or crash the game." In C, those forbidden moves are undefined behavior. The tricky part: the computer is allowed to assume you'll never make a forbidden move, so it skips safety checks to go faster. That's great when you obey, but if you slip up, even moves you made earlier can go wrong. So the lesson is simple: never make the forbidden moves — don't read past the end of a list, don't use a thing after you threw it away, don't make a number too big to fit.
Dekho yaar, C ka standard ek contract hai compiler ke saath. Kuch galtiyan aisi hain jinhe karne par standard kehta hai "ab mera koi responsibility nahi" — isi ko Undefined Behavior (UB) kehte hain. Matlab program crash bhi ho sakta hai, sahi bhi chal sakta hai, ya silently data corrupt kar sakta hai. Sabse khatarnaak baat: UB sirf buggy line ko nahi, poore program ke meaning ko todh deta hai, kyunki compiler maan leta hai ki "programmer ne promise kiya tha ki ye UB kabhi nahi hoga", aur isi assumption pe wo aapke safety checks tak delete kar deta hai (jaise signed overflow wala example).
Important difference yaad rakho: signed overflow (INT_MAX + 1) UB hai, lekin unsigned overflow defined hai — wo modulo 2n wrap karta hai. Isliye jab wraparound chahiye to unsigned ya uint32_t use karo. Baaki common UB: null/dangling pointer dereference, array ke bahar likhna-padhna, use-after-free, double free, uninitialized variable padhna, i = i++ jaisa sequencing issue, aur string literal modify karna.
Sabse bada trap yeh hai: "mere machine pe to chal gaya" — ye proof nahi hai ki code sahi hai. UB kabhi chal jaata hai, phir naye compiler ya -O2 flag pe break ho jaata hai. Isliye hamesha check pehle karo, calculate baad mein (jaise x > INT_MAX - 100), har variable initialize karo, aur testing mein -fsanitize=undefined,address aur -Wall -Wextra lagao. Yahi 20% effort hai jo 80% UB bugs pakad leta hai.