Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How a compiler knows from a header file, that a source file exists somewhere?

I just started to learn C/C++, but I'm a bit confused. I often see the #include preprocessor directive, with a header file argument:

#include <stdio.h>
#include <iostream.h> 
#include "windows.h"
#include <math.h>

But sometimes the .h is missing:

#include <iostream>

I already know, that the header file contains the signatures of the functions only, and some preprocessor commands. But when and how does the compiler include the math functions, if I include math.h?

If I create a library, then where to put the .c/.cpp/.h files, and how to include them?

like image 707
Iter Ator Avatar asked Nov 18 '15 12:11

Iter Ator


3 Answers

When you install the compiler, the standard header and library files are also installed into well-known locations. For example, on a Linux or Unix system, the standard headers are typically installed under /usr/include or /usr/local/include and the standard libraries are typically installed under /usr/lib or /usr/local/lib.

When you #include the header file, the compiler will look for it in different places depending on whether you use the angle brackets (#include <stdio.h>) or quotes (#include "myfile.h"). For example, if you include a header file in angle brackets, gcc will search for that header in the following directories:

/usr/local/include
libdir/gcc/target/version/include
/usr/target/include
/usr/include

If you include a header file with quotes, gcc will first search the current working directory, then additional directories as specified by command-line options, and finally the standard include paths above.

Most compilers allow you to specify additional include paths as arguments to compile command, such as

gcc -o executable-name -I /additional/include/path source-files

But sometimes the .h is missing:

#include <iostream>

This is the C++ convention1; C++ standard headers do not have the .h extension, I guess to make it look more object-oriented than it really is (that is, you can pretend you're importing the class directly, rather than including the text of the file that describes the class).

I already know, that the header file contains the signatures of the functions only, and some preprocessor commands. But when and how does the compiler include the math functions, if I include math.h?

The implementations of the math functions are typically kept in a separate library (code that's already been compiled and archived into a single binary file); depending on the compiler, the math library may or may not be automatically linked into the executable. For example, gcc does not automatically link in any math library functions, even if you include the math.h header file. You have to explicitly include the math library as part of the build command:

gcc -o executable-name command-line-options source-files -lm

With gcc, the convention is that -lname links in a library named libname.a2. The standard math library file is named libm.a, so -lm tells gcc to link in the machine code that's contained within libm.a.

Like the standard headers, the compiler will search for the standard libraries in well-known locations. You can specify additional search paths for libraries that aren't part of the standard installation, like so:

gcc -o executable-name command-line-options source-files -L /additional/library/path -ladditional-library

If I create a library, then where to put the .c/.cpp/.h files, and how to include them?

You can put the files pretty much anywhere you want; you'll specify where they are as part of the build command. So, say you're creating a new library named mylib. You create a new directory under your home directory:

mkdir ~/mylib
cd ~/mylib

Then you create and edit your source files and headers:

cd ~/mylib
vi mylib.h
vi mylib.c

To build mylib as a static library, do the following:

cd ~/mylib
gcc -c mylib.c
ar libmylib.a mylib.o

So when you're done, the directory ~/mylib contains the following:

libmylib.a
mylib.c 
mylib.h
mylib.o

To use the functions collected in mylib in a program, you'd specify the header and library include paths as part of the compile command:

gcc -o executable-name command-line-options source-files -I ~/mylib -L ~/mylib -lmylib

So, if you include "mylib.h" in another program, this will tell the compiler to search for that header in ~/mylib, and it will tell the linker that the libmylib.a library will be found under ~/mylib.

In a real-world situation you'd handle all of the builds with makefiles instead of building everything by hand. You'd also probably set it up so that as part of the build process, all the headers that anyone else would need to use your library would be copied to a separate include subdirectory, and the library would be written to a separate lib subdirectory, so you could distribute your library without exposing your source code. In that case, the build command above would look more like:

gcc -o executable-name command-line-options source-files -I ~/mylib/include -L ~/mylib/lib -lmylib


1. This hasn't always been the case; the earliest implementations of C++ used iostream.h, vector.h, etc. I'm not sure exactly when that convention changed, but it's been a while.

2. Actually, I'm not sure anymore if this is a gcc convention or a *nix convention; the two have been joined at the hip for so long it's hard to remember sometimes.

like image 167
John Bode Avatar answered Oct 17 '22 03:10

John Bode


Actually, the compiler doesn't know anything about other source files, it only knows about the current translation unit. It's the job of the linker to take all translation units and link them together with the libraries to create the executable program, and it's the linker that will resolve all definitions and that notice missing function definitions.

Traditionally, working with C or C++ is a four step process:

  1. Edit files
  2. Compile source files into object files
  3. Link object files and libraries to generate the executable program
  4. Run the program.

The preprocessor is usually built into the compiler, so preprocessing and compiling is only a single step.


As for the "missing" .h, none of the C++-only standard library header files have that extension.

like image 42
Some programmer dude Avatar answered Oct 17 '22 03:10

Some programmer dude


Standard Template Library headers, such as < algorithm > include source code for the template functions, which get instantiated at compile time, based on the template type(s) involved in source code calls to template functions.

A library is a collection of object files in a single library file. The linker normally only includes the object files needed to satisfy the references to functions or data to build the program, not the entire library file. The exception to this is a dynamic link library, since all of that library will be loaded (if not already loaded) at program load time.

The compiler has default locations for headers using < > and using " ". The headers using " ", can include relative or absolute paths. The relative path may vary depending on the tool set.

like image 1
rcgldr Avatar answered Oct 17 '22 01:10

rcgldr