name mangling and ABI stability
C++ lets you overload functions — several functions can share the name max but take different argument types. The linker, however, works with flat symbol names and has no notion of types or overloads; it just needs every function to have one unique name. Name mangling is how the compiler bridges this gap: it encodes the function's namespace, name, and full argument types into a single decorated symbol, so max(int) and max(double) become two distinct, unique symbols the linker can tell apart.
Concretely, a function like int ns::max(int, int) might be mangled into something like _ZN2ns3maxEii — an encoding of the namespace ns, the name max, and the two int parameters. This is what makes overloading and namespaces work at link time, and it is why a C++ name in a linker error or a backtrace looks like line noise (tools like c++filt demangle it back to readable form). To call C functions from C++ unchanged, you wrap them in extern "C", which tells the compiler to use the plain, unmangled C name — this is exactly how C++ code links against C libraries. ABI, the application binary interface, is the broader contract for how compiled code interoperates at the binary level: how arguments are passed in registers, how the stack is laid out, how objects and vtables are arranged, and how names are mangled.
Why it matters: ABI stability is the promise that code compiled separately — your program and a precompiled shared library, or two halves built by different compiler versions — will agree on these binary conventions and link and run correctly. The honest difficulties are real and recurring: the C ABI on a platform is famously stable for decades, but the C++ ABI is far more fragile — changing a class's layout (adding a member, changing inheritance), or mixing objects built with incompatible compiler or standard-library versions, can silently corrupt memory at run time with no compile error. Mangling schemes also differ across compilers, which is one reason C, with its simple stable ABI, remains the lingua franca for library boundaries even between C++ programs.
extern "C" int add(int, int); // suppresses C++ mangling so the symbol is plain 'add' and links against a C library or is callable from C
extern "C" gives a function the unmangled C symbol name, the bridge that lets C++ and C link to each other.
An ABI mismatch is uniquely nasty because it usually compiles and links without error and then corrupts memory at run time: mixing two objects that disagree on a class's layout is undefined behavior, not a diagnosed error. This is why mixing standard-library or compiler versions across a binary boundary is so risky.