As a coding rule that I follow, any function (other than main()) that is visible outside its source file needs a declaration, and that declaration should be in a header.  I avoid writing 'extern' declarations for functions in my source files it at all possible, and it almost always is possible.
If a function is only used inside a single source file, it should be static.  That makes it much easier to modify; you know that the only place you need to look to see how it is used is the source file you have in front of you now (unless you make a habit of including '.c' files in other '.c' files - which is also a bad habit that should be broken now).
I use GCC to help me enforce the coding rule:
gcc -m64 -Wall -Wextra -std=c99 -Wmissing-prototypes -Wstrict-prototypes
That's a fairly typical collection of flags; I sometimes use -std=c89 instead of -std=c99; I sometimes use -m32 instead of -m64; I don't always use -Wextra (but my code is moving in that direction).  I always use -Wmissing-prototypes and -Wstrict-prototypes to ensure that each external function is declared before it is defined or used (and each static function is either declared or defined before it is used).  I occasionally use -Werror (so if the compile emits a warning, the compilation fails).  I could use it more than I do since my code does compile without warnings - or gets fixed so that it does.
So, you could easily have been looking at my code.  In my code, the only functions that are exposed - even in single source file programs - are the functions that are declared in a header, which means that they are part of the external interface to the module that the source file represents.