20

I'm not interested in the source code, I want to know how the C compiler (GCC) actually finds the functions. As in, when the preprocessor sees that I've included stdio.h, where does it look to find the files that define the function bodies?

Edit

I should probably also say I'm using Ubuntu 12.04, but if there's a general answer, that would work too.

Tyler
  • 2,579
  • 2
  • 22
  • 32

5 Answers5

26

gcc comes with (binary) object files (not C source files) which contain implementations of all the standard C functions. When you use gcc to link object files into an executable file, the linker automatically includes the object files which implement the standard library functions. According to this thread, that standard object file will probably be called libc.a or libc.so.

Say you include a call to printf in your program. When the linker tries to resolve where that call should go, it will find the definition of printf in libc.a, and make your function call point there.

Look at http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html and note the -nostdlib and -nodefaultlibs options. You can use these options to tell gcc's linker not to include the standard library object files by default.

Community
  • 1
  • 1
Alex D
  • 29,755
  • 7
  • 80
  • 126
  • So does the linker automatically include object files that implement *all* the standard library functions every time? If so, what's the point of associating different functions with different header files, if they all get included anyway? – Tyler Mar 08 '14 at 22:37
  • The *object files* are used by the `gcc` *linker*. The *header files* are used by the *compiler*. The compiler needs to see the headers, so it knows the function signatures and thus 1) can type-check the code, and 2) can generate the right code for passing arguments and getting the return value. Why didn't they put the signatures for *all* the standard library functions in a single header file? Well, for one thing, it would be non-compliant with the C standard, since the C standard actually defines what the standard header files should be. For another thing, it would make compile times slower. – Alex D Mar 09 '14 at 19:56
  • Also, @Tyler, the linker doesn't include object files from a static library unless they are needed. The .a file is an indexed library of separate object modules, and the linker will include only those that resolve an undefined symbol (and some of those may reference new undefined symbols, so it will keep going). In the case of a .so, the whole library will be loaded at runtime, so this does not apply. – greggo Jun 16 '15 at 17:30
13

gcc obtains the function definitions from the C library. You could determine the path that gcc would look into, by default, for it by saying:

ld --verbose | grep SEARCH_DIR

This leads to /usr/lib on my system.

Lets try to find if the library contains the symbol for a standard function, say scanf:

nm -A /usr/lib/libc.so | grep scanf

The results include:

/lib/libc.so:0000000000042a90 T scanf

Consider a small example:

#include <stdio.h>

int main() {
  printf("Hello World!\n");
  return 0;
}

Lets call it i.c:

$ gcc i.c              # Compile
$ ldd ./a.out          # Try to find dependencies
./a.out:
        -lc.12 => /usr/lib/libc.so.12

The last command essentially implies that the binary depends upon /usr/lib/libc.so.12 and that you'd find the definitions of the functions used in the code therein.

devnull
  • 118,548
  • 33
  • 236
  • 227
4

Your question has to do with where GCC searches for header files. It searches the standard include directories. You may find this thread to be useful:

With various options (such as -I and -I- and -isystem) you can specify lots of different inclusion features. Basically, directories specified by -I will be searched before those specified by -isystem, which will in turn be searched before those in the "standard system include directories" (at least, according to my tests). The difference is that -I can be used for any #include directive, but -isystem will only be used for #include <...> That said, though, it is recommended to only use -I for #include "..." directives because of the search order. Using -I- really gives you a lot of control because any -I used before -I- will be searched for only for #include "..." whilst any -I used after -I- will be searched for any #include directive. In addition, using -I- means that the current directory will not be searched for included files unless you also specify -I. (search the current directory).

If you want to get a listing of what search directories are supported by default, try running this command: cpp -v < /dev/null This runs the GNU C Preprocessor with no input; in the process it will print (given the -v flag) the inclusion directory search paths. You should see phrases like "#include <...> search starts here:" followed by a list of directories. Those are your standard inclusion search paths, in the order that they're searched.

djhaskin987
  • 9,741
  • 4
  • 50
  • 86
  • 1
    This is somewhat tangential to where the libraries are found, though if the headers are found by default in `/some/path/include`, the libraries are usually found in `/some/path/lib`. – Jonathan Leffler Mar 07 '14 at 03:56
2

Your libc (or libstdc++ for C++) might be located in either /usr/lib or /usr/lib64 on Linux. These are shared libraries and you can modify the LD_LIBRARY_PATH variable to specify what directories they're searched in. A practical example would be you install a local copy of gcc and chances are it will have an updated version of the standard library as opposed to your system, so you would want your local gcc to start up with that instead, i.e export LD_LIBRARY_PATH=/home/user/local-install/gcc/lib64

sleske
  • 81,358
  • 34
  • 189
  • 227
1

It looks into the library paths set by the environment variable.

Read more: http://gcc.gnu.org/onlinedocs/cpp/Search-Path.html

brokenfoot
  • 11,083
  • 10
  • 59
  • 80
  • 1
    He's not asking where `gcc` finds the standard headers. He's asking where it finds the *bodies* of those functions. – Alex D Mar 07 '14 at 03:48