Ability or desire to inline function or not compiler decides on its own regardless of inline
or static
keywords. As long as compiler sees function definition in translation unit it compiles, then it can decide to inline - regardless where it is defined. Regular C function, function in C++ namespace, member function in C++ class, operator overloads, template functions/classes, etc...
First of all you should forget about "header" files or #include's. For compiler they do not exist. Those are only preprocessor things. Compiler does "copy&paste" to take #include content and put in place where it included. Only then it actually compiles source file that produces one object file. This is called translation unit. All these static/inline/extern keywords mean something only in context of translation unit, headers do not mean anything.
Also by word "symbol" everywhere I mean global function or variable - they both work the same regardless static & extern keywords.
What static/inline/extern keywords do - they define symbol linkage. By default all global symbols in C are extern. Meaning they produce symbol in object file. And other translation units can call this function by name or use variable by name. This means you cannot have same named symbol in different translation units. Sometimes you want that, sometimes not. This also slows down compilation & linking process - they need to process a lot of symbol names this way.
There are minor differences in C++, for example, symbols inside anonymous namespaces do not produce "public" symbol - other TU's won't be able access it.
This is avoided by static keyword. What this keyword does is to make symbol "private" - only visible to current translation unit. This is called "internal linkage". This is great - compiler compiles faster (no need to put it public symbol table), and linker links faster (less symbols to process). If you place same named function/variable in multiple TU's that means compiler will optimize & codegen each place with its own copy of function/variable. Linkers have special step where they collect duplicated function bytes to generate only one copy in output binary, but that's implementation detail.
Third option is if you put inline keyword in front of function. This is kind of legacy from old C compilers and in my opinion should not be used in modern codebases. What it does is to generate function code same as static
case inside translation unit, but still place its name in public symbol table with special marker saying it is "inline". This can happen in multiple translation units, so when linker links everything together, it won't error out like in "extern" case with duplicate symbol error - it will see this marker and simply take any copy it wants. This means every single translation unit must provide exactly same function as inline. Otherwise it is violation of "one definition rule" - and compiler is allowed to produce garbage output as result.
So technically with inline
function some other TU could still access it by having extern declaration of it.
There some other minor differences between these static/inline/extern things, I just gave high level overview. You should read about them in details in documentation:
https://en.cppreference.com/w/c/language/storage_duration
https://en.cppreference.com/w/c/language/inline
And if you have not see Chat 13 episode, watch it - because it goes into details of translation units and how compilers & linkers work: https://guide.handmadehero.org/chat/chat013/