interface (header) versus implementation (library)
A library has two parts that play very different roles. The interface is the promise — the list of functions you may call, with their names, parameters, and return types — and it lives in a header file. The implementation is the fulfilment — the actual compiled machine code that does the work — and it lives in the library file. A restaurant menu (interface) tells you what you can order and what it costs; the kitchen (implementation) actually cooks it, and you never see inside.
Concretely, when you write #include <foo.h>, you are pulling in declarations: lines like 'int foo_add(int a, int b);' that tell the compiler such a function exists, what arguments it takes, and what it returns — but not how it works. That is enough for the compiler to check your calls and generate code that calls foo_add. The how lives separately in the compiled library (libfoo.a or libfoo.so), which the linker attaches afterwards. The header is the contract; the library is the body. They are matched but distinct, and you can ship a header to users without ever revealing the source code behind it.
Why it matters: this separation is what lets you use a library by knowing only its interface, while its authors are free to rewrite the implementation, as long as the contract stays the same. It also explains a common pair of errors: include the header but forget to link the library, and you get a linker 'undefined reference' (interface found, implementation missing); link the library but forget the header, and the compiler does not know the function's signature. Both halves are needed, and they fail in different, recognizable ways.
foo.h (interface): int foo_add(int a, int b); // declaration only foo.c (implementation): int foo_add(int a, int b){ return a + b; } Users #include "foo.h" to call foo_add, and link libfoo to get the code.
The header declares what you can call; the compiled library provides how it is actually done.
Including a header is not the same as linking the library: the header gives the compiler the function's shape, but without the compiled implementation the linker still fails with 'undefined reference'. Interface and implementation are separate and both required.