How Does a C/C++ Compiler Find the Definitions of Prototypes in Header Files

How does a C/C++ compiler find the definitions of prototypes in header files?

The compiler doesn't do this, the linker does.

While the compiler works on one source file at a time, when the linker is invoked it is passed the names of all of the object files generated by the compiler, as well as any libraries that the user wishes to have linked in. Therefore, the linker has complete knowledge of the set of files that could potentially contain the definition, and it needs only to look in the symbol tables of those object files. It doesn't need to do any searching beyond that.

For example, say you have foo.h and foo.c defining and implementing function foo(), and bar.h and bar.c defining and implementing bar(). Say bar calls foo so that bar.c includes foo.h. There are three steps to this compilation:

gcc -c foo.c
gcc -c bar.c
gcc foo.o bar.o -o program

The first line compiles foo.c, producing foo.o. The second compiles bar.c, producing bar.o. At this point, in the object file bar.o, foo is an external symbol. The third line invokes the linker, which links together foo.o and bar.o into an executable called "program". When the linker processes bar.o, it sees the unresolved external symbol foo and so it looks in the symbol table of all of the other object files being linked (in this case just foo.o) and finds foo in foo.o, and completes the link.

With libraries this is a bit more complicated, and the order that they appear on the command line can matter depending on your linker, but it's generally the same principle.

Should the header file containing function prototypes be included in file with definitions?

Yes you should because it makes sure that the function signature is the same in the declaration and the definition. If they don't match the program won't compile. It is also a good idea to include myfunc.h before any other include file in myfunc.c. That way you will know that the header file is self-contained.

When including headers in a C program, how does the linker/compiler find the corresponding code?

You need to distinguish between headers and libraries.

Headers declare facilities that are available to programs. When you include a header such as <stdio.h> (NB: this is not — repeat not! — a library), you make available to the compiler the information necessary to use the facilities from the standard I/O library. In general, C headers do not define the actual code that implements the facilities. C++ has 'header only' libraries (some parts of Boost are prime examples of 'header only' libraries).

Libraries provide the implementation of the facilities. The <stdio.h> header declares a function fopen(); there is a library somewhere that defines that function.

Some headers (actually, typically, it is a lot of headers) are privileged and the facilities that they declare are included in the standard library that the C compiler links your programs with. You don't have to do anything special to get the functions linked into your program. Other headers are from libraries that the C compiler does not know about a priori, and for those, you have to tell it where to find the library (e.g. with -L /opt/sometool/lib as a compiler option) and the library name (e.g. with -lsometool, which might link with /opt/sometool/lib/libsometool.so or /opt/sometool/lib/libsometool.a). Note that the headers for SomeTool are probably in /opt/sometool/include, and you'd need to add an option -I/opt/sometool/include to find the sometool.h header.

The linker doesn't reference headers; the compiler proper doesn't reference libraries. The compiler control program does handle the mixture (it typically runs multiple phases of the compilation process as separate programs — the compiler is separate from the linker). The headers do not contain information about where the library is installed.

Function Prototypes in C

  1. size_t is more appropriate returned value for strlen rather than int
  2. __cdecl is a calling convention for a function. This signifies who sets up a stack for parameters, return value etc and who clears it. More reference: Calling convention
  3. While declaring a function, you don't really need parameter names. Just parameter type is sufficient.

Update for extern :

  • extern tells to compiler that the statement is just a declaration and not definition. So for functions prototypes, extern doesn't add any value as it already just a definition. Reference: C Extern

Hope this helps.

Why should we include header file of a function prototype in the same file that the function is declared?

To answer this question, you should have a basic understanding of the difference between the compiler and the linker. In a nuttshell, the compiler, compilers each translation unit (C file) alone then it's the linker's job to link all the compiled files together.

For instance, In the above code the linker is the one who is searching where the function foo() called from main() exists and links to it.

The compiler step comes first then the linker.

Let's demonstrate an example where including file2.h in file2.c comes handy:

file2.h
void foo(void);
file2.c
#include <stdio.h>
#include "file2.h"

void foo(int i) {
printf("%s:%s:%d \n", __FILE__, __func__, __LINE__);
return;
}

Here the prototype of foo() is different from its definition.

By including file2.h in file2.c so the compiler can check whether the prototype of the function is equivalent to the definition of it, if not then you will get a compiler error.

What will happen if file2.h is not included in file2.c?

Then the compiler won't find any issue and we have to wait until the linking step when the linker will find that there is no matching for the function foo() called from main() and it will through an error.

Why bother then if the linker, later on, will find out the error anyway?

Because in big solutions there might be hundreds of source codes that take so much time to be compiled so waiting for the linker to raise the error at the end will waste a great amount of time.

Functions in C Headers?

No, just putting the .c with the .h and including it in your code doesn't magically carry over the definition of the functions too.

You need to compile the foo.c separately into an object file (in case of Linux, it is a .o file). For example using the command -

gcc -c foo.c -o foo.o

Now this foo.o needs to be linked to your actual program. This can be done by simply passing the object file while compiling as

gcc test.c foo.o -o test.out

If you do not link the foo.o with your program, your linker won't be able to find the implementations for the functions defined in it and will throw a linker error as -

Undefined reference to function foo_function.

How do you define functions in header files?

You should only write your function's prototype in the header file, the body of your function should be written in a .c file.

Do this :

primary_header.h

/* primary_header.h */
#ifndef PRIMARY_HEADER_H
#define PRIMARY_HEADER_H

#include <stdio.h>

/* Forward declare the primary workhorse function */
void primary(void);

/* Also define a helper function */
void helper(void);

#endif /* PRIMARY_HEADER_H */

primary_impl.c

/* primary_impl.c */
#include "primary_header.h"
#include <stdio.h>

/* Define the primary workhorse function */
void primary()
{
/* do the main work */
printf("I'm the primary function, I'm doin' work.\n");

/* also get some help from the helper function */
helper();
}

void helper()
{
printf("I'm a helper function and I helped!\n");
}

Edit: change _PRIMARY_HEADER_H to PRIMARY_HEADER_H. As @Jonathan Leffler and @Pablo said, underscore names are reserved identifiers



Related Topics



Leave a reply



Submit