I'm looking at a header-only C "library": https://github.com/zserge/jsmn/blob/master/jsmn.h
As far as I can understand, this code will be compiled into every object file where the .c file includes jsmn.h, wasting space.
(The file's function definitions are inside #ifndef JSMN_HEADER, so you could use this as a "traditional" header file by defining JSMN_HEADER.)
Why hasn't it been written as a "traditional" .c and .h pair?
Is the linker clever enough to dedup function identical definitions between object files? I would have expected "duplicate symbol" errors.
What advantage does putting code in headers give in C? (Not C++.)
From where do you get the function definitions if you use #define JSMN_HEADER before importing?
Is jsmn.h being header-only a clever trick, from which I can learn?
The header expands into one of the following, depending on the macros defined:
No macros — function definitions (public functions are non-static, private ones are).
JSMN_HEADER — function declarations (for public functions only).
JSMN_STATIC — static function definitions (for both private and public functions).
If only a single TU needs the library, you can freely choose between (1) and (3).
If more than one TU needs the library, you need (1) in one of the TUs and (2) in all others. Then the only thing that's "wasted" is preprocessor time for skipping function definitions for (2), but it shouldn't matter since they're so tiny.
In this case, trying to go with (1) for all TUs would give you "duplicate symbol" linker errors. Trying to go with (3) for all TUs would silently duplicate the symbols, which would be wasteful.
Why hasn't it been written as a "traditional" .c and .h pair?
For supposed convenience of distributing and using the library.
Is the linker clever enough to dedup function identical definitions between object files? I would have expected "duplicate symbol" errors.
It's probably not clever enough, but it doesn't need to be.
You're expected to define the macros so that only a single TU has the definitions.
What advantage does putting code in headers give in C?
Less source files to distribute.
From where do you get the function definitions if you use #define JSMN_HEADER before importing?
From your other TU that didn't define this macro before including the header.
Is jsmn.h being header-only a clever trick, from which I can learn?
Yes.
Related
I understand the static keyword is used for creating functions or variables which are "private" to the translation unit (the source file).
However, as far as I understand, in order to make sure a particular function or variable is not accessible from outside the .c file that it was declared in, I can simply not declare it in the corresponding .h file.
For example:
f.c
void public_func() {
// ...
}
void private_func() {
// ...
}
f.h
void public_func();
// no declaration of private_func
So why should I also declare private_func as static? Is that simply a convention or does it have a technical benefit over simply not declaring it in the .h file?
The problem is that compilers work on "translation unit" basis, meaning one .c file and all the .h files it includes. So it is traditionally not able to detect naming collisions across the whole project.
So if you don't make it static, the function has "external linkage" per default. Meaning if have a function private_func and another translation unit in the same project is using the same name, you get namespace collisions during linking and linker errors.
It is also a matter of correctness - private functions/variables should simply not be accessible from the outside, neither intentionally nor accidentally.
I understand the static keyword is used for creating functions or variables which are "private" to the translation unit (the source file).
That's true.
Is that simply a convention or does it have a technical benefit over simply not declaring it in the .h file?
There is a technical point here. Once compiler is done doing it's job it produces an object file. That file has a symbol table, which is later used by linker when the linker puts a program together from separate object files. static functions will not get into that table, so that direct references to that function from other object files will fail with "unresolved reference" error in the linking stage.
Benefits? Well you save some tiny space in you object file, linking stage will go faster, since there will be a smaller table to process. But that's tiny enough to not make a difference, unless we're talking about a made up case of thousands of functions with loooong names.
If you have a non-static function and you omit it's declaration in the header file, the function name still gets into a symbol table. And if I happen to know the declaration somehow (other than from the header) I can still call/reference the function directly from another translation unit, no linker error will happen.
Let's say you write a library that consists of several .c and .h files. The clients of your library will need to use some of the header files to use your library. They should only see the public functions.
But for the implementaiton of your library, you might also use header files so functions in your library can call other (internal) functions.
So you end up with two types of declarations:
For clients of your library
void public_func();
For internal use
static void private_func();
Preferrably, the private and public declarations are in separate header files and the clients of your library only need to include the header files with public functions.
This question already has answers here:
C: Why do we include header files, which declare but don't define?
(5 answers)
Closed 4 years ago.
This is the question I still cannot answer by myself (probably due to lack of experience in C).
So I found this answer and the question is what's wrong with putting definitions into a header files? I we don't declare them as static it should be fine since they will have external linkage and linker will not complain.
Secondly, why should not we put static definition into a header file? Suppose we want to make some function sort of "compilation-unit private" that is not intended to have external linkage.
And what I was surprised about was why is it (rarely) possible to put inline function definition into header files?
Is it just by convention only?
There is not usually any point in putting information into a header unless it will be included in multiple other source files. That means that if the header defines some variables, each source file that includes the header will define those variables. And it is normally an error to define the same (global) variable more than once. So, putting variable definitions into a header normally defeats the reason for creating a header in the first place.
Note that C does have a 'one definition rule', similar to C++, but not as strong. There is a 'common' extension — complete with double entendre — that often allows you to get away with defining a variable in more than one file, but it doesn't work if the variable has a non-trivial initialization.
You can find a lot of information in How do I use extern to share variables between source files?, including information about the common extension.
You should not normally define static variables in a header because that means that each file that includes the header will define its own copy of the variables. This is usually not what's wanted. It tends to make programs bigger.
If you reliably work with compilers that support inline, there is no particular reason why you can't put static inline function definitions into a header. There is a risk that if the function cannot be inlined, then the compiler will generate a static function in the object code for each source file that uses the function, again increasing the size of the executable. You might be able to avoid that by using non-static inline function definitions. If the functions are small enough that they will be inlined, there is no particular reason not to put them in a header.
You can find more information about inline functions, with static or extern, in the Q&A on Stack Overflow:
extern inline
Is inline without static or extern ever useful in C99
What's the difference between static and static inline functions?
Note the rather extensive use of weasel words such as 'usually' and 'normally' in the answer above. You can, with care, find exceptional situations that warrant breaking the rules, but if you remember that headers are the glue that provide cross-checking between the code that uses some functionality (types, constants, functions, sometimes variables) and the code that implements the functionality, then you'll realize that it is good to follow these rules:
Headers declare types, constants, enumerations, functions, variables that are used by multiple source files.
Source files implement functions and define variables that are used by multiple source files.
The header files are used by the implementation code to ensure that the implementation matches the specification.
The header files are used by the consumer code to follow the source-level rules for the implementation.
Header files should not define variables.
Source files should not declare external variables; they should include the relevant header.
Headers may sensibly define static inline functions; you may even include plain inline function definitions in a header, but you have to be careful to instantiate the functions somewhere in case they are not inlined — and that's when extern inline comes into play. (Be aware that old GCC rules for inline functions are different from C99 standard rules.)
There are some rules that simply including a header won't enforce, such as required sequences for calling functions (don't call a free function before the corresponding allocate function, for example). But using headers wisely prevents a lot of errors.
See also:
Should I use #include in headers?
How to link multiple implementation files in C?
And many other questions, no doubt.
Do I need to declare all functions I use in a .c file in a header file, or can I just declare and define right there in the .c file? If so, does a definition in the .c file in this case count as the declaration also?
Do I need to declare all functions I use in a .c file in a header file,
or can I just declare and define right there in the .c file?
You used "use" in the first question and "define" in the next question. There is a difference.
void foo()
{
bar(10);
}
Here, foo is defined and bar is used. You should declare bar. If you don't declare bar, the compiler makes assumptions about its return type.
You can declare bar in the .c file or add the declaration in a .h file and #include the .h file in the .c file. Whether you use the first method or the second method is up to you. If you use the declaration in more than one .c file, it is better to put that in a .h file.
You can define foo without a declaration.
If so, does a definition in the .c file in this case count as the declaration also?
Every function definition counts as a declaration too.
For the compiler, it does not matter if a declaration occurs in a .h or a .c file, because the compiler sees the preprocessed form.
For the human developer reading and contributing to your code, it is much better (to avoid copy&pasting the same declaration twice) to put the declaration of any function used in more than one translation unit (i.e. .c file) in some #include-d header.
And you can define a function before using it.
BTW, you might even avoid declaring a function that you are calling (it defaults to returning int for legacy purposes), but this is poor taste and obsolete way of coding (and most compilers can emit a warning in that case).
No, it is not necessary.
The reason of the header files is to separate the interface from the implementation. The header declares "what" a class (or whatever is being implemented) will do, while the .c file defines "how" it will perform those features.
This reduces dependencies so that code that uses the header doesn't necessarily need to know all the details of the implementation and any other classes/headers needed only for that. This will reduce compilation times and also the amount of recompilation needed when something in the implementation changes.
The answer to both questions is yes. You can declare c-functions in both header and .c file. Same with definition. However, if you are defining it in header file, you may have slight problems during compilation.
By default functions have external linkage. It means that it is supposed that functions potentially will be used in several compilation units.
However sometimes some auxiliary functions that form implementations of other functions are not designed to be used in numerous compilation units. Such functions declared with keyword static have internal linkage.
Usually they are declared and defined inside some .c module and are not visible in other compilation units.
One occasion that requires functions to be declared in a separate header is when one is creating a library for other developers to use. Some libraries are distributed as closed source and they are provided to you as a library file (*.dll / *.so ...) and a header.
The header file would contain declarations of all publicly accessible functions and definitions of all publicly required structures, enums and datatypes etc.
Without this header file the 3rd party library user would not know how to interface with the library file and thus would not be able to link against it.
But for small, trivial C programs that are not intended for use by other people, no you can just dump everything into a C file and build it. Although you might curse yourself years later when you need to maintain that code :)
I'm using eclipse indigo, gcc and cdt in a project. If two functions in separate source files share names (regardless of return type or parameters), eclipse flags a redefinition error. This isn't a huge issue regarding this project given I can easily rename these functions, and I'm well aware of wrappers if it were. Although this isn't a critical issue, it does make me think I'm not understanding the c build process. What occurs during the build process in which a program structure like this would cause issue?
Here's some more info. on the situation, and where my understanding is so far -- not necessary to answer the question, although there must be a hole in my understanding.
In this case, the two functions are intended to be used only locally, as such their prototypes are not given in the .h interface, and for the sake of my point, neither are defined 'static'.
Neither of these source files are being included anywhere in the project, so they shouldn't be sharing any compilation units. With that in consideration, I would have assumed that the neither source file is aware of the presence of the other, and the compiler would have no problem indexing the two functions, as the separate files would allow for proper distinguishing between the two during linking -- so long as they weren't included in the same compilation unit.
I noticed that statically defining either instance of the function declaration removes the error. I remember reading at some point that every function not declared static is global -- although given these functions are not a part of the .h interface, the practical example in which including the .h interface doesn't allow for the including program to reference all .c functions would indicate "hiding" these functions would be of no issue.
What am I overlooking?
Some insight would be greatly appreciated, thanks!
This is the concept of "linkage". Every function and variable in C has a linkage type, one of "external", "internal", and "none". (Only variables can have no linkage.)
Functions have external linkage by default, which means that they can be called by name from any compilation unit (where "compilation unit" roughly means one source file and all the headers it includes). This can be expressed explicitly by declaring them extern, or it can be overridden by declaring them static. Functions declared static have internal linkage, meaning they can be referenced by name only from other functions in the same compilation unit.
No two external functions anywhere in the same program can have the same name, regardless of header files, but static functions in different compilation units may have the same name. A static function may have the same name as an external function, too -- then the name resolves to the static function within its compilation unit, and to the external function elsewhere. These restrictions make sense, for otherwise it would be possible for a function call to be ambiguous.
Header files don't factor into the linkage equation at all. They are primarily a vehicle for sharing declarations, but a function's linkage depends only on how it is declared, not on where.
I leave discussion of variables' linkage for another time.
It doesn't matter whether one source module includes headers for another. Header files only contain declarations for the purpose of local functions being able to find functions in other modules. It doesn't mean that functions not declared don't exist from the perspective of that module.
When everything gets linked together, anything not specifically defined to be local to one source module (i.e. static) has to have a unique name across all linked components.
remember reading at some point that every function not declared static is global
Having understood this you got the main point and reason for the behaviour observed.
.h files are not known to the linker, after pre-processing there are only translation units left (typically a .c file with all includes merged in), from which .o files are compiled.
There are no interfaces on language level in C.
Neither of these source files are being included anywhere in the project, so they shouldn't be sharing any compilation units.
Declare those functions as static. This is the only way to "hide" a function from the linker "inside" a translation unit.
C doesn't "mangle" function names the way C++ or Java do (since C doesn't support function polymorphism).
For example, in C++, the functions
void foo( void );
void foo( int x );
void foo( int x, double y );
have their names "mangled" into the unique symbols1
_Z3fooid
_Z3fooi
_Z3foov
which is how overloaded function/method calls are disambiguated at the machine level.
C doesn't do that; instead, the linker sees two different function definitions using the same symbol and yaks because it has no way to disambiguate the two.
1. This is what happens on my system, anyway
I'm creating a large program that's supposed to be simulating a MIPS pipeline. I'm trying to modularize my code as much as possible to keep things simple, but I'm having trouble compiling.
Currently my program contains the files:
pipe.c --- Containing main
IF.h
ID.h
EX.h
MEM.h
WB.h
global.h --- containing global #define functions
reg.h
ALU.h
control.h
dMem.h
fBuffer.h
parser.h
bin.h
I'm new to C programming but I have protected myself against multiple includes using #ifndef, #define, #endif in every header file. My problem is that when I compile I get errors claiming: "previous implicit declaration of..."
Many of the header files are used by multiple files, so I'm not sure if this is the issue. Is there some sort of big thing that I'm missing?
an implicit declaration means that there was something that wasn't declared in a header (instead, the compiler simply found the function). a previous implicit declaration means that it's come across the declaration later, after assuming an implicit declaration for a "raw" function (or, i guess, as Doug suggests in the comments, another function with the same name).
there are a number of ways this can occur:
maybe you didn't include the header in the associated file. so IF.c doesn't include IF.h. the compiler will read IF.c and create the implicit definition. later, when it reads IF.h somewhere else, it will give this error.
maybe you use a function in a file that doesn't include the relevant header. so maybe IF.h defines myfunction(), but you use myfunction() in dMem.c and don't include IF.h there. so the compiler sees the use of myfunction() in dMem.c before it sees the definition in IF.h when included in IF.c.
without header files at all, you can get this with mutually recursive functions. see How to sort functions in C? "previous implicit declaration of a function was here" error
as Doug suggested, you define two functions with the same name (and don't have a definition in a header).
basically, somewhere, somehow, the compiler got to a function before it got to the header with the associated declaration. when it did find the header it realised things were messed up and generated the error.
(one classic source of header errors is cut+paste the "ifdefs" from one file to another and forget to change the name...)
[reading your question again i assumed you'd only listed the header files. but now i see that is all the files you have. why do you have so many more headers than source files? typically each source file is associated with one or two headers that contain the declarations for the functions it defines (although it will likely import others that it needs for support). this is unrelated to your compiler error, but it sounds like maybe you need to split your source up. it also suggests that either i have misunderstood you, or you are misunderstanding how headers are typically used.]