Challenge 3: Why C Cannot Overload Functions, and Why extern "C" Is Needed — Possible Solution ==================================================================== Per the chapter, C compiles every function name into a PLAIN, UNMANGLED linker symbol -- the function's own name in source becomes, essentially unchanged, the exact symbol the linker uses to resolve calls to it (c2-5's own linking material covers this directly: the linker matches an unresolved reference in one object file against a matching DEFINITION in another, by symbol name). If a C program defined two functions both named print, the linker would have no way to distinguish which definition a given call was supposed to resolve to -- there is only ONE possible symbol name, "print," that both definitions would collide on, so C's compiler rejects this outright as a redefinition error before it ever reaches the linker. C's linking model was never designed with a mechanism to have more than one distinct definition live under a single name. C++ makes overloading possible specifically by NOT using the plain function name as the linker symbol at all -- name mangling encodes each function's parameter types into a genuinely different symbol (e.g. _Z5printi vs. _Z5printd). From the linker's own perspective, print(int) and print(double) were never actually the "same name" to begin with; they're two entirely distinct symbols that just happen to share a readable source-level name. The linker itself didn't change or get smarter -- C++ simply gives it different names to work with. Why extern "C" is necessary for interop: a C compiler has no concept of name mangling at all -- when C code calls a function, or when a C library exposes a function for others to call, it expects to find (or provide) a symbol with the PLAIN, unmangled name. If C++ code compiles a function without extern "C", its real linker symbol is the mangled form -- which a C compiler/linker would never generate or look for, causing linking to fail entirely when the two try to interoperate. extern "C" tells the C++ compiler "use plain, C-style linkage rules for this declaration specifically" -- producing an unmangled symbol name that a C caller (or C library) can actually find and match against, bridging the two languages' otherwise incompatible linker-symbol expectations. WHY THIS WORKS AS AN ANSWER ------------------------------ This ties C's inability to overload directly to its plain, unmangled symbol-naming scheme (not a vague "C is simpler"), explains precisely how mangling solves it by generating genuinely different symbols per overload, and explains extern "C" as resolving a genuine mismatch between C's and C++'s different symbol-naming expectations rather than an arbitrary compatibility flag.