C - Header files - c

C requires different headers files, like stdio.h, stdlib.h, fcntl.h, etc.,for different functions and structure definitions, why is that? Underneath the hood it all boils down to libc so why not create a single header file with all the definitions and prototypes?

These files are provided by the C standard library to make accomplishing common tasks easier. As to why the declarations and definitions are kept in separate files, it's for convenience and maintainability reasons. The same reason why, for example, the Linux kernel is not defined in a single C file, even though theoretically it could be.

The separate header files are defined the way they are largely due to historical compatibility. The C language was already being used on a variety of platforms before it was standardized.
The rationale behind the separate header files was likely a way to mimic modularity within the C language. Separate header files defined functionality provided by a module. This is not too different from how other languages provide functionality.
C also has a philosophy of minimalism, and so requiring every translation unit to compile the prototype declarations of all available functions regardless of whether they were going to be used would seem excessive.

Such things are not required by C.
It is possible, if you wish, to manually copy the contents of any header file into every source file, and do without the header file. However, that is error prone - if one of the source files changes, it is often necessary to update ALL the source files, and that makes it easy for typos to creep in. (If you copy the content of standard headers to all your compilation units, your code may also fail if built with a different compiler/library, since the content of the headers varies between implementations).
Including header files is simply a technique which allows the content of the header file to be (effectively) copied and pasted into every source file that includes it - and all source files get the SAME content (unless some other preprocessor macros cause things to happen conditionally). For standard headers (particularly those which provide functionality that can only be implemented in different ways on different systems) that aids portability.

Related

Is it ok to store functions in header files that aren't shared across multiple source files?

What if you have a minimal amount of structures, functions and macros but want to exclude them from the source file to convert the source code into a more concise and readable format and reduce the amount of lines of code.
Is structures, functions or macros/data in general accessible/viewable from examining the binary even if the data is not called within the source code? And if so how?
For the sake of readability is it safe to cut structures, functions and macros from a source file into a header file that is used by multiple source files even if some source files don't use all of the structures, functions and macros (for small header files)?
Is structures, functions or macros/data in general accessible/viewable
from examining the binary even if the data is not called within the
source code?
Depends on what you build. If you build a library (.a, .so, .lib, .dll, whatever) they're probably in there and everything in that library is accessible in some way. If you build an executable the linker will most likely remove unused code.
Have a look at nm
For the sake of readability is it safe to cut structures, functions
and macros from a source file into a header file that is used by
multiple source files
Yes and no. Put declarations of functions/structs in header files and their implementations in .c files. Don't put a lot of unrelated functions and structs in one header. You end up including all those declarations in every source file even though you're using 5% of them. That means extra work for your compiler, probably some extra work for your linker and extra work for your and future programmers brains when reading all this unnecessary stuff.
So, guessing what's happening in your code base, you probably want to put them in seperate header files.
Be careful when using macros and even more when putting them in header files. You should avoid this most of the time.
even if some source files don't use all of the structures, functions
and macros
That is quite common. You include some standard C headers too and don't use all of the functions and structs in there right? Just (as I said) put together what belongs together.

What is the point of linking 2 source files instead of using a header file?

Why should I use another source code file to share code or a function between many programs and use the linker instead of using a header file only? (I read this in Head First C but I didn't understand what is the point of it)
Generally, header files should only be used to declare your functions/structs/classes.
The actual implementation should be created in a separate .c file which then can be built and exported as a binary along with the header.
Keeping the implementation in the header has many drawbacks.
Bigger footprint - the header size will be bigger since you have
more symbols in it.
You cannot hide the implementation from the end-user.
The compile-time will be a lot larger since all code has to be processed every time it is included by the compiler.
Just to name a few. They might be many more reasons.
However, there are some cases when it is okay/better to include some logic in the header files.
For example for inline functions which may improve the runtime of the application while maintaining good code quality and/or templates in C++.
Generally, header files contain declarations, like function signatures, while the function definitions (the actual source code) are located in separate source files.
Multiple files can include the same header file and share function declarations at compile time. But they also must share the source files (the files must be linked together) in order to have access to the function code at run time.

Do including header files make the program heavier in c

Do including header files such as stdio.h, conio.h or any other makes our code or program heavier
Including header files inserts all the content from them into the translation unit on pre-processing.
If the include has only declarations(which is usually the case) and the functions are implemented in library files, the code doesn't get heavier. If the header files include implementation, it will be compiled on compilation, thus making the file heavier.
You can read more about compilation steps here:
http://www.tenouk.com/ModuleW.html
Why don't you try including them and building an EXE, then not including them and building an EXE, and see what happens to the file size. I suspect you'll find that the linker is clever enough to only build what's necessary into the EXE.
For typical release builds, no. Header files typically only contain declarations, and unused declarations do not contribute to the size of release builds. Header files can contain inline function definitions, which might be emitted by your compiler if the definition is not optimized out. However, this will probably not apply to system headers like <stdio.h>.
For typical debug builds, yes. Debugging data often contains information about declarations even if those declarations aren't used in the program. This way you can use those declarations in the debugger. Modern debuggers include function definitions, enums, and even preprocessor definitions these days.
That said, you can put anything in a header file.
The primary effect of unnecessary header file inclusions is to make the build process take longer.
Normally a header file contains declarative statements only. Declarations in themselves do not add to code size. Referencing the declared symbols anywhere in the code will cause the linker to include the code defining the declared symbols.
Because a header file must be parsed by the compiler in the context of the code in which it is included, the build time can be extended by header file inclusion. Very large or deeply nested headers such as windows.h for example can have a considerable effect in this way.
Additionally if you are using an IDE with code navigation and comprehension facilities such as auto-complete and syntax checking, the IDE must parse the code in a similar manner to the compiler, and here again header files can slow that process down.
While you should avoid including unnecessary header files, those containing declarations fuse in teh code are unavoidable - or at least avoiding them will lead likely lead to errors, repetition and make the code hard to maintain.

Header per source file

I'm trying to understand the purpose behind one header per each source file method. As I see it, headers are meant for sharing function declarations, typedef's and macro's between several files that utilize them. When you make a header file for your .c file it has the disadvantage that each time you want to see a function declaration or macro you need to refer to the header file, and generally it is simpler that everything is in one source file (not the whole software, of course).
So why do programmers use this method?
The header files in C separate declarations (which must be available to each .c file that uses the functions) from the definitions (which must be in one place). Further, they provide a little modularity, since you can put only the public interface into a header file, and not mention functions and static variables that should be internal to the .c file. That uses the file system to provide a public interface and private implementation.
The practice of one .h file to one .c file is mostly convenience. That way, you know that the declarations are in the .h file, and the definitions in the corresponding .c file.
Logical, structured organisation and small source files enable:
faster, better programming - breaking the code into more manageable and understandable chunks makes it easier to find, understand and edit the relevant code.
code re-usability - different "modules" of code can be separated into groups of source/header files that you can more easily integrate into different programs.
better "encapsulation" - only the .c files that specifically include that header can use the features from it, which helps you to minimise the relationships between different parts of your code, which aids modularity. It doesn't stop you using things from anywhere, but it helps you to think about why a particular c file needs to access functions declared in a particular header.
Aids teamwork - two programmers trying to change the same code file concurrently usually cause problems (e.g. exclusive locks) or extra work (e.g. code merges) that slow each other down.
faster compiles - if you have one header then every time you make a change in it you must recompile everything. With many small headers, only the .c files that #include the changed header must be rebuilt.
easier maintainability & refactoring - for all the above reasons
In particular, "one header for each source file" makes it very easy to find the declarations relevant to the c file you are working in. As soon as you start to coalesce multiple headers into a single file, it starts to become difficult to relate the c and h files, and ultimately makes building a large application much more difficult. If you're only working on a small application then it's still a good idea to get into the habit of using a scalable approach.
Programmers use this method because it allows them to separate interface from implementation while guaranteeing that client code and implementation agree on the declarations of the functions. The .h file is the "single point of truth" (see Don't Repeat Yourself) about the prototype of each function.
(Client code is the code that #include's the .h file in order to use the exported functions, but does not implement any of the functions in the .h.)
Because, as you said yourself, it is not feasible to put the "whole software" into one source file.
If your program is very small, then yes it's is simpler just to put everything in one .c file. As your program gets larger, it becomes helpful to organize things by putting related functions together in different .c files. Further, in the .h files you can restrict the declarations you give to declarations of things that are supposed to be used by things in other .c files. If a .c file doesn't contain anything that should be accessible outside itself, it needs no header.
For example, if .c has function foo() and fooHelper(), but nobody except foo() is supposed to call fooHelper() directly, then by putting foo() and fooHelper() into foo.c, only putting the declaration of foo() in foo.h, and declaring fooHelper() as static, it helps to enforce that other parts of your program should only access foo() and should not know or care about fooHelper(). Kind of a non object-oriented form of encapsulation.
Finally, make engines are generally smart enough to rebuild only those files which have changed since the last build, so splitting into multiple .c files (using .h files to share what needs to be shared) helps speed up builds.
You only put in your header file the bare minimum that other source files need to "see" in order to compile. I've seen some people that put everything non-code into the header file (all typedefs, all #define's, all structures, etc.) even if nothing else in the codebase will be using those. That makes the header file much harder to read for yourself and those who want to use your module.
You don't need one header per source file. One header per module, containing the public interface, and maybe an additional header containing private declarations etc shared between files in that module.
Generally a header for a source file method means that you declare only the functions from that compilation unit in that header.
That way you don't pollute with declarations you don't need. (in large software project might be a problem)
As for separate compilation units, these speed up the compilation and can help you avoid collisions if private symbols are declared static.

C project structure - header-per-module vs. one big header

I've worked with a number of C projects during my programming career and the header file structures usually fall into one of these two patterns:
One header file containing all function prototypes
One .h file for each .c file, containing prototypes for the functions defined in that module only.
The advantages of option 2 are obvious to me - it makes it cheaper to share the module between multiple projects and makes dependencies between modules easier to see.
But what are the advantages of option 1? It must have some advantages otherwise it would not be so popular.
This question would apply to C++ as well as C, but I have never seen #1 in a C++ project.
Placement of #defines, structs etc. also varies but for this question I would like to focus on function prototypes.
I think the prime motivation for #1 is ... laziness. People think it's either too hard to manage the dependencies that splitting things into separate files can make more obvious, and/or think it's somehow "overkill" to have separate files for everything.
It can also, of course, often be a case of "historical reasons", where the program or project grew from something small, and no-one took the time to refactor the header files.
Option 1 allows for having all the definitions in one place so that you have to include/search just one file instead of having to include/search many files. This advantage is more obvious if your system is shipped as a library to a third party - they don't care much about your library structure, they just want to be able to use it.
Another reason for using a different .h for every .c is compile time. If there is just one .h (or if there are more of them but you are including them all in every .c file), every time you make a change in the .h file, you will have to recompile every .c file. This, in a large project, can represent a valuable amount of time being lost, which can also break your workflow.
1 is just unnecessary. I can't see a good reason to do it, and plenty to avoid it.
Three rules for following #2 and have no problems:
start EVERY header file with a
#ifndef _HEADER_Namefile
#define _HEADER_Namefile_
end the file with
#endif
That will allow you to include the same header file multiple times on the same module (innadvertely may happen) without causing any fuss.
you can't have definitions on your header files... and that's something everybody thinks he/she knows, about function prototypes, but almost ever ignores for global variables.
If you want a global variable, which by definition should be visible outside it's defining C module, use the extern keyword:
extern unsigned long G_BEER_COUNTER;
which instructs the compiler that the G_BEER_COUNTER symbol is actually an unsigned long (so, works like a declaration), that on some other module will have it's proper definition/initialization. (This also allows the linker to keep the resolved/unresolved symbol table.) The actual definition (same statement without extern) goes in the module .c file.
only on proven absolute necessity do you include other headers within a header file. include statements should only be visible on .c files (the modules). That allows you to better interpret the dependecies, and find/resolve issues.
I would recommend a hybrid approach: making a separate header for each component of the program which could conceivably be used independently, then making a project header that includes all of them. That way, each source file only needs to include one header (no need to go updating all your source files if you refactor components), but you keep a logical organization to your declarations and make it easy to reuse your code.
There is also I believe a 3rd option: each .c has its own .h, but there is also one .h which includes all other .h files. This brings the best of both worlds at the expense of keeping a .h up to date, though that could done automatically.
With this option, internally you use the individual .h files, but a 3rd party can just include the all-encompassing .h file.
When you have a very large project with hundreds/thousands of small header files, dependency checking and compilation can significantly slow down as lots of small files must be opened and read. This issue can be often solved by using precompiled headers.
In C++ you would definitely want one header file per class and use pre-compiled headers as mentioned above.
One header file for an entire project is unworkable unless the project is extremely small - like a school assignment
That depends on how much functionality is in one header/source file. If you need to include 10 files just to, say, sort something, it's bad.
For example, if I want to use STL vectors I just include and I don't care what internals are necessary for vector to be used. GCC's includes 8 other headers -- allocator, algobase, construct, uninitialized, vector and bvector. It would be painful to include all those 8 just to use vector, would you agree?
BUT library internal headers should be as sparse as possible. Compilers are happier if they don't include unnecessary stuff.

Resources