Reputation:
I've heard that you put function prototypes in header files and then put the function definitions in a .c file. However, what is this .c file. For example, if you were to include a file "foo.h", would you call the aforementioned .c file "foo.c", put the function definition in it, put it in the same place as the foo.h, and when you try to include foo.h, will the function carry over from the c file and will the function be ready to use?
Upvotes: 1
Views: 2921
Reputation: 1
Header files are just conventional. The C preprocessor is handling #include
directives and the compiler sees the preprocessed input (but you might copy and paste huge amount of C code to get the equivalent of #include
). Actually, the preprocessor don't care if you #include "foo.h"
or #include "foo.c"
, but the later is often poor taste. Naming header files with a .h
suffix is just a (very common) convention.
So, if you have a function definition in a header included in several source files (technically translation units), that function definition is in every such translation unit.
What happen then depends on that function definition (it should be static
or even better static inline
).
In practice, you should restrict function definitions in header to be static
or static inline
. If you don't declare static
a function definition void foo(int x) { /* something */ }
in a header which is included in several *.c
files you'll have multiple-definitions of foo
errors at link time. And the main interest of putting a function definition in a header is to enable inlining (hence the inline
hint); otherwise (the usual case), you don't need that and you just put the function prototype in the header file and the function definition in one of your *.c
files.
If you have short and quick running functions, it could be wise to define them as static inline
(so give their bodies) in your header files (but of course, that increases the compilation time). Otherwise, it is not worth the burden.
Some header files might have long macros (of dozens of physical lines, all of them except the last ended with a backslash) expanded to function definitions. Look into sglib for an example.
Notice that inline
is today (like register
was in the previous decade) just a hint to the compiler (for inline expansion optimization), which is allowed to ignore it (also, many optimizing compilers are able to inline functions without any annotation, provided they know the body of the called function).
Don't forget to enable all warnings and debug info. With GCC, use gcc -Wall -Wextra -g
, perhaps with -Wstrict-prototypes
. You could get the included files with -H
(and the preprocessed form with -C -E
).
Refer to some C reference site and to the C11 standard n1570 for more details. Read the GNU cpp
reference manual about preprocessing.
Upvotes: 1
Reputation: 9213
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
.
Upvotes: 3