Functions in C Headers? - c

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?

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.

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.

Related

Why doesn't the compiler need to be passed the respective source files when including headers from the standard library?

When you include a header
#include "foo.h"
you also need a source file, foo.c, with the definitions of the prototypes in the header that you pass to the compiler when compiling: gcc main.c foo.c. Why doesn't the same have to happen for headers from the standard library? For example, say you have a main.c file with
#include <stdio.h>
when you compile, you don't have to then write gcc main.c stdio.c, you just write gcc main.c.
Why is this? Does the compiler/linker know where to look for the source files when you compile and just automatically adds them? If not, then how would the compiler know what to do with the function prototypes?
When you have a header file called foo.h it doesn't necessarily mean that the there should be a source file associated with it called the foo.c. There can be be independent source and header files.
When you do compile a simple C code, hello_world.c
#include <stdio.h>
int main() {
// printf() displays the string inside quotation
printf("Hello, World!");
return 0;
}
And when you compile the code, the code is first preprocessed as part of this the header file inclusion happens and any header file that is to be included and is present within the </> (#include <stdio.h> in our case) is searched for it's definition in the current directory and a few predefined search path already know to the compiler (the preprocessor). Few of the standard header file definitions are present such as /usr/include, /usr/local/include, etc. more info
The second part of your question being as to how does the compiler know the definition of say for example printf() when we don't associate a source file at compile time that is cause when you compile any program the compilers by default links it with a std C library called the libc which contains the definition of functions such as scanf,printf,etc
When you include a header /* ... */ you also need a source file
No, you do not have to.
Your header file may contain only macro and data types declaration. No source file needed
The code was compiled before and you have only library or object files. You need to let know the linker that it has to use those files.
You use standard library files. generic linker needs to know the library locations. Many compilers pass this information on their own. for example gcc uses spec files where you may specify where your libraries are (and many more things).

How to correctly include own libraries in function files and project files

I got stuck trying to do Exercise 8-3 of K&R, the goal of the exercise is to rewrite some functions of stdio.h such as fopen, fclose, fillbuf and flushbuf
here's how my source files are organized:
stdio.h: contains types and macro definitions, and the declarations of some functions proper to the library. all content of the file is enclosed between #ifndef #endif lines as follows:
#ifndef STDIO_H
#define STDIO_H
/* content of stdio.h */
#endif
myfunction.c: I have a .c file per function, each file has a #include "stdio.h" line to load all needed types definitions.
main.c: where I have code to test my functions, the main.c also has a #include "stdio.h" line.
my problem is the following: when I try to compile all my files using gcc I run to the error:
multiple definition of `_iob'
on every one of my function files where my stdio.h is included, (_iob is a variable I only defined inside my stdio.h)...why is this happening ? I though the #ifndef line was to specifically prevent such errors.
more generally:
How would you go about making your own header files and library/function files and using them in your projects ?
Is there a way to make the linker figure out the position of my functions just by including the header file, the same way it does for standard functions ?
Please become aware of the difference between a library and its header files.
A library is a (collection of) binary machine code (with some additional meta-data, e.g. relocation directives to the linker).
For example, on my Linux system, dynamic libraries are generally shared objects (e.g. /usr/lib/x86_64-linux-gnu/libgmp.so) and it makes absolutely no sense to try some preprocessor directive like #include "libgmp.so" //wrong.
But a library has some API. That API is given by some documentation and by some header file(s), e.g. gmp.h and you should #include "gmp.h" in any C code (your C translation unit) which uses it.
myfunction.c: I have a .c file per function
Having one file per function is often poor taste. You generally can group related functions. For example, in your case, you probably want to define your myfopen and myfclose functions in the same myopenclose.c translation unit (even if you don't have to) because these two functions are intimately related. As a rule of thumb, I prefer having source files of one or a few thousand lines each (but that is really a matter of taste, and some people like having many small files).
Remember that what the compiler really sees is the preprocessed form of code. Consider asking your compiler to produce that form (e.g. from foo.c you can get its preprocessed form foo.i with gcc -C -E -Wall foo.c > foo.i on my Linux desktop) and look into it. Try that on your own files (e.g. your myopenclose.c if you have one).
If you have many small files, the compiler is probably including the same headers in each of them, and these included declarations gets compiled every time. BTW, notice that gcc is only a driver program. Use it with -v flag. You'll see that it is running cc1 (the C compiler proper), as (the assembler), ld (the linker), etc.
I run to the error:
multiple definition of `_iob'
on every one of my function files where my stdio.h is included, (_iob is a variable I only defined inside my stdio.h).
You probably should declare extern your _iob global variable in your stdio.h and define a global _iob in only one implementation file (perhaps myopenclose.c, if it is relevant) of your library.
Don't confuse definition and declaration (of variables, functions, types, etc.). Spend some time reading the C11 standard n1570. These words are defined there. As a rule of thumb, declarations should go into header .h files, definitions (of variables and functions) in implementation .c files (of course details are much more complex, you often but not always define types and struct in header files).
I strongly recommend using some Linux distribution (it is very developer- and student- friendly) and studying the source code of some existing free software C standard library (like musl-libc, whose code is quite readable). More generally, study the source code of existing free software projects (e.g. on github). They will inspire you.
Is there a way to make the linker figure out the position of my functions just by including the header file, the same way it does for standard functions ?
This shows a lot of confusion (the above question does not make any sense). Read more about compilers (your cc1 program -started by gcc- is translating a .c file into some object file .o) and about linkers (your ld, generally started by gcc, is agglomerating several object files, processing relocations inside them, and producing an ELF library or an executable). The preprocessing (e.g. of #include directive) is done at compile time by cc1. The linker cannot see any header files (it only deals with object files or libraries).
If you rewrite some of the system declarations and functions, while at the same time including the system declarations, you can expect some collisions.
Header files (.h) contain code (usually only declarations) and the mechanism you describe (#ifndef STDIO_H) is to prevent multiple inclusions of the same header file - mainly because another include file (header) that has already been loaded might also include it. That result in the same kind of collision as you had.
In C, you could, for instance
make a new header file that contain your own declarations + the stdio ones that don't collide with yours
use the stdio declarations, and only write new functions that use the same structures, defines, enums etc... as stdio
rewrite the necessary declarations and code that allows you not to include the system headers anymore
use another naming convention, like my_iob in both your header file, and in your code.
The two last ones are probably the best in your case, since you still have some collisions coming from a header file.
For instance, your code might not include stdio.h, but another header file you include might do it, indirectly...

Compiler warning not generated for multiple definitions

problem I am facing is function with same signature is defined in two .c files and is not giving compile time error. I have included declaration in .h file, which is included to both .c files.
For example:
int add(int x, int y) { return x+y;}
same definition is given in two .c files (Say A.c and B.c) and declaration in one .h file which is included in both A.c and B.c. But why this is not giving compile time error or How can I make to give them compile error
Even Linker is not giving any error, it looks it is taking first definition
I am using GCC compiler mingw
I found another pattern in this.
if I am using this in header file
#ifndef H_H_
#define H_H_
linker is not giving warning warning but If i don't use this Linker gives warning which is expected.
This situation is undefined behaviour with no diagnostic required.
Consult your linker's documentation to see if it has any options to report multiple definition of functions.
The compiler doesn't analyze your program as a whole. It simply processes one .c file at a time. If the declaration in the .h file matches the definition in the .c file, then everything is good as far as the compiler is concerned.
The linker will detect that the function was defined twice and will generate a "duplicate symbol" error.
Compiler sees each source file apart from the other. Compiler includes the content of header file(s) into A.c then geneates an object file A.obj from A.c. A.obj file will contain symbols of the variables and functions defined in A.c. On the other hand, compiler will process B.c apart without checking A.c, or any other source file, content. It will start by including header file(s) into B.c then it generates B.obj which also includes symbols of the variables and functions defined in B.c.
As a result, you will not get errors at compile time as the function duplication is not detected by the compiler. It is the linker job to check the symbols consistency and that there are no duplication present. Linker will get all generated object files in order to generate an executable. Linker must assign a unique memory address to each symbol. For example, in your code if there is a point (let's say in main function) where a function of A.c is called, actually, this is translated into a jump to an address in memory where that function is located. Now, imagine if two functions with the same signature coexist in the executable and each symbol has a different address. Then, how can the processor figure out which function exactly do you intend to call in your program. For that reason, if linker finds a symbol which is duplicated it will signal an error.
As #Matt-McNabb says: consult your linker documentation.
The only other cause I can come up with is that the linker binary compares the two functions, finds they are idenical, and ignores one. You can check this by slightly changing the code, for example by 'return y+x'.

Detect undefined symbols in C header file

Suposse I coded a C library which provides a bunch of "public" functions, declared in a mylib.h header file. Those functions are supposedly implemented in (say) a mylib.c file which is compiled to a (say) static lib mylib.c -> mylib.o -> mylib.a.
Is there some way to detect that I forgot to provide the implementation of some declared function in mylib.h? (Yes, I know about unit testing, good practices, etc - and, yes, I understand the meaning of a plain function declaration in C).
Suppose mylib.h declares a void func1(); and this function was not coded in the provided library. This will trigger an error only if the linker needs to use that function. Otherwise, it will compile ok and even without warnings - AFAIK. Is there a way (perhaps compiler dependent) to trigger a warning for declared but not implemented functions, or there is any other way to deal with this issue?
BTW: nm -u lists not all undefined declared functions, but only those "used" by the library, i.e., those functions that will trigger an error in the linking phase if not declared somewhere. (Which makes sense, the library object file does not know about header files, of course.)
Basically, the most reliable way is to have a program (or possibly a series of programs) which formally exercise each and every one of the functions. If one of the programs fails to link because of a missing symbol, you've goofed.
I suppose you could try to do something by editing a copy of the header into a source file (as in, file ending .c), converting the function declarations into dummy function definitions:
Original:
extern int somefunc(void);
Revised:
extern int somefunc(void){}
Then compile the modified source with minimum warnings - and ignore anything to do with "function that is supposed to return a value doesn't". Then compare the defined symbols in the object file from the revised source with the defined symbols in the library (using nm -g on Unix-like systems). Anything present in the object file that isn't present in the library is missing and should be supplied.
Note: if your header includes other headers of your own which define functions, you need to process all of those. If your header includes standard headers such as <stdio.h>, then clearly you won't be defining functions such as fopen() or printf() in the ordinary course of events. So, choose the headers you reprocess into source code carefully.
There's no easy way.
For example, you can analyse the output of clang -Xclang -ast-print-xml or gcc-xml and filter out declarations with no implementations for a given .h file.
You could grep for signatures of exported function in both .h and .c, and compare the lists.
Use wc -l for counting matches, Both numbers should be equal.
Another thought, just came to my mind. It is ihmo not possible to handle it using compiler. it is not always the case, that function declares in mylib.h is implemented in mylib.c
Is there some way to detect that I forgot to provide the implementation of some declared function in mylib.h?
Write the implementation first, then worry about header contents -- because that way, it can be flagged.

Compiling with header files

Why do I have to specifically compile a C source file with:
gcc prog.c -lm
even when I have already included the specific header file with:
#include <math.h>
The #include file tells the compiler how a function looks like, as in what type it returns, how many parameters of what types it takes, but it doesn't tell the compiler the contents.
The -lm flag includes that actual math library which contains the code for the functions to be called.
It works the same way with printf(), fread() and other standard functions. When you include stdio.h, you don't actually include the code of the function but the definitions. Because the C library is implicitly linked without you having to do anything about that, you don't notice it.
Because you need to inform the compiler which math library to link with, nothing to do with the math.h inclusion.
Similarly to your own code, which should have header files (.h) for function declarations and source files (.c) for function definitions, the code for the math library is in two parts. The header file, which you include, contains the function declarations:
double sqrt(double n);
However, it doesn't contain anything about how these functions work. This code is in a separate file which you have to link in, similarly to how you link different source files to create an application.
Because in C, there is technically absoultely no connection between the header file and the library. There can be more header files than libraries, or the other way round. It's just a matter of convention (and of course it makes some sense) to have a 1:1 relation in most cases.

Resources