As I was going through a huge source code, I came across some files where there is only one function declared in, let's say, "code.h" but in "code.c" there are many functions declared and defined.
What is the exact use of declaring and defining functions in .c files ?
How can we access one of those functions in a source file from other source file ?
It would be helpful if anyone can provide an example. Thanks
Splitting a complex routine in multiple smaller routines might make the code easier to understand and also would allow you to follow the single responsibility principle (What is an example of the Single Responsibility Principle?). By declaring and defining them only in a .c file (and declaring them static), you can hide the internal details from users.
If you, for instance, create a library, then your header could only show the public functions you'd like your users to use.
So only put your functions in a header if you'd like those functions available to anyone who includes the header.
If you'd like to keep a function internal to your .c file, seriously consider adding the static keyword as well: what is the advantage of static function?
---edit---
How can we access one of those functions in a source file from other source file ?
If the function isn't static, you could technically declare it anywhere* you'd like and use it there as well. Though, by the above argument, this would be bad practice.
Example:
a.c
int secret_a(int x)
{
return x+1;
}
main.c
#include <stdio.h>
//access a secret function from a.c
int secret_a(int);
int main()
{
printf("secret_a(3) gives: %d\n", secret_a(3));
return 0;
}
(*) anywhere allowed by the C language
How can we access one of those functions in a source file from other source file ?
That is the whole idea with defining some functions in the header, and some only in the c-file.
The functions defined in the header, can be called by other source files.
The functions only defined in the source file, can be hidden - it is a usual practice to mark functions, only declared in a source file, as static.
That makes their visibility limited to the file-scope (only code inside the same file can 'see' the functions).
The reason why this is done is to split the code into a more cleaner and sorted format so that functions concerning a particular operation can be grouped together in to one file and then called from other file. NOTE: this is not mandatory to do but a good programming practice.
Now there are two ways to do it :
1. including the files
2. Declaring the function as extern and then linking them at linking time.
1.
Including the file is the method that you are probably seeing in your code at hand. Functions are defined in one file and that file is included using #include"filename.[h/c]" and then calling the function as it were declared in the given file.
file_to_include.c
void my_func()
{
printf("Hello!\n");
}
file_that_include.c
#include<stdio.h>
#include"file_to_include.c"
int main()
{
my_func();
return 0;
}
to compile you just do
gcc file_that_include.c
using extern you can do the same but with out using the #include directive
file_to_include.c
void my_func()
{
printf("Hello!\n");
}
file_that_include.c
#include<stdio.h>
extern void my_func();
int main()
{
my_func();
return 0;
}
In this case while compiling you need to provide both files to the compiler
gcc file_that_include.c file_to_include.c
I would suggest reading up on the "extern" keyword.
From what I can understand in your question you have two files - "code.h" and "code.c". However, "code.h" only declares certain functions in "code.c":
code.h
int func1();
int func2();
code.c
int func1()
{
return 1;
}
int func2()
{
return 2;
}
int func3()
{
return 3;
}
main.c
#include "stdio.h"
#include "code.h"
extern int func3();
int main()
{
printf("%d ", func1());
printf("%d ", func2());
printf("%d ", func3());
}
Compiling using gcc:
gcc main.c code.c
yields:
main.c: In function ‘main’:
main.c:10:17: warning: implicit declaration of function ‘func3’ [-Wimplicit-function-declaration]
printf("%d ", func3());
and when executed:
1 2 3
The "extern" keyword basically tells the compiler "there is a definition for a function with this declaration" for compiling. During linking the linker will find the definition, and link to it.
This is however a clumsy way of doing it, since the caller ("main.c") needs to know what is going on in "code.c", and continually add more extern declaration, etc. etc.
So rather include functions you which to have global scope in "code.h". If there are functions in "code.c" which od not have global scope, consider making them "static".
Some more reading:
Effects of the extern keyword on C functions
Related
My goal is to write a library which exposes only a public API in C language.
Let's say I'm writing a library, and it depends on two other libraries: a.c, and b.c
Contents of a.c:
int a(void) { return 1; }
Contents of b.c:
int b(void) { return 2; }
And let's say my library is m.c and its contents are:
#include "a.h"
#include "b.h"
int m(void) {
return a() + b();
}
My goal is to hide int a(void) and int b(void) so that they don't pollute the global namespace. I want the only symbol to be exported to be int m(void). That is, if my user defines their own a, they shouldn't get a link error:
#include "m.h"
int a(void) { // SOME OTHER FUNCTION
return 5;
}
int main(void) {
return m() + a();
// THIS WOULD CREATE A LINK ERROR,
// SINCE THERE ARE TWO `A` FUNCTIONS
// IN SYMBOL TABLE
}
The only thing that comes to mind is to define macros with the same name as a and b like this:
#define a internal_a
#define b internal_b
This would create name-mangled symbols, and once user has an executable, they can strip away internal dependency symbols using strip -s file.elf
Another way would be to design internal dependencies as UNIX style filter programs. However, this would require serialization, and would only work if all the internal dependencies belong to me.
Both methods are not ideal, so I'd like to see if there are any better ways to achieve this in C. I'm also not sure how C++ solves this. Most probably the symbols C++ exposes have names namespace-funcname-params.
edit: This would be trivial if I had all my dependencies in a single file. I'd simply use static keyword where needed. My question is specifically about multiple file libraries.
edit: Even though standard C doesn't provide a portable solution for this, the problem is still very common in programming. So, solutions might not be directly relevant with C, but more with the build tools (compiler, linker, preprocessor..)
I'm new to C programming and I just started studying functions.
Should I put each function in a .c and .h file, or can I put all of the functions and headers in one .c and .h file?
Determining where to put different parts of your code is something that comes with both your personal and the programming language experience. Considering your mention that you're currently learning about functions, let me go over a couple main factors in deciding where to put your functions.
Prototypes
When writing your code, before you can use a variable, you need to declare it first. The same goes for functions. The first, simple approach is defining a function before you use it.
int add(int a, int b) {
return a + b;
}
int main(void) {
int result = add(10, 8);
return 0;
}
Here I defined a function add() and called in the function main(). This piece of code will simply compile and run. However, what if I placed my definition of the add() function below the main() function?
int main(void) {
int result = add(10, 8);
return 0;
}
int add(int a, int b) {
return a + b;
}
This piece of code will result into a compilation error. The compiler doesn't know which add() function I'm calling in the main() function, because no add() function has been defined yet. Sometimes you can solve this problem by simply re-arranging the code. Other times that is not possible and that's why prototyping comes into play.
int add(int a, int b);
int main(void) {
int result = add(10, 8);
return 0;
}
int add(int a, int b) {
return a + b;
}
This tells the compiler there is a function add() accepting two int parameters, that will be defined later in the code. The compiler is satisfied and indeed - this piece of code compiles without an issue once again.
The #include directive
Including headers in C is a bit troublesome. It is the method of including the definitions in header files inside your .c files, and it's done in the simplest way imaginable - every #include <my_header.h> directive in your C code gets simply replaced with all contents of the my_header.h file before the compilation. For example imagine the following files:
my_header.h
// Hello, I am the my_header.h file
// I currently have no definitions
my_program.c
#include "my_header.h"
int main(void) {
// Do nothing
return 0;
}
If I compile just my_program.c, the preprocessor will examine the file before the compiler does. It will find an #include directive, look for a file named my_header.h, find it and copy its contents into the .c file simply like this:
// Hello, I am the my_header.h file
// I currently have no definitions
int main(void) {
// Do nothing
return 0;
}
Then the resulting file will be given to the compiler.
While this approach is incredibly simple and easy to implement, it makes C very prone to errors and hard to maintain, unless great care is taken. This is for example the reason include guards exist. Imagine you include two files in your main file. Now both of those two files include one, third file. After all the replacements done, you'll end up having the third file pasted twice inside your code, which will result in naming conflicts during a compilation.
This also means you technically can put any sort of code inside the header files. However, in my whole career, I was met with only one case when such code was acceptable (in a bare metal embedded system program), so I can't stress this out enough - unless you really, really know what you're doing, never put anything other than function prototypes, variable declarations, includes and macros inside a header file. Doing otherwise is the easiest way to have your code break in the most inexplicable of ways.
The conclusion
The style I've seen the most often (and also personally follow) is separating sets of functions with similar functionalities into individual .c files. This .c file contains nothing, but function definitions (i.e. the code) and a single #include directive of the header file this .c file is associated with. This keeps all the functions in a separate translation unit.
The header file with include guards (isn't needed when you don't include the file more than once anywhere, but it's a good habit to get used to) contains all the required #include directives of system libraries, other header files in your project and function prototypes of every function in the respective .c file. Whenever you then need to use those functions elsewhere, include this header file in any other header file. System libraries are generally included using <> while your own files are included using "".
As remarked by other answers, the .c file containing the main function often exists without its respective header file. All other .c files should have a header file associated. This is mostly in line with the Google's C++ Style Guide.
An example
For any smaller project, you most likely won't need more than just two files. Take these as an example:
main.h
#ifndef _MAIN_H_
#define _MAIN_H_
#include <stdio.h>
// any other includes
int add(int a, int b);
int sub(int a, int b);
int main(int argc, char *argv[]);
#endif // _MAIN_H_
main.c
#include "main.h"
int main(int argc, char *argv[])
{
int first = 10;
int second = 8;
int third, fourth;
third = add(first, second);
fourth = sub(third, first);
return 0;
}
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
If you were to add more mathematical functions, say mul() and div(), it'd be appropriate to take them all out of the main.c file and create a new pair of files - something along the way of my_math.c and my_math.h, following the same rules as the rest of your project. Then, to call the mul() function in your main function, you'd need to #include my_math.h inside main.h.
A lot of this comes with the experience. Feel free to explore other styles and try out what works the best for you. The most important part in all of this is staying consistent. Pick a style and stick to it. Best of luck in your studies!
Should every function (definition) in C have its own .c file?
No. should not, but can. It's a matter of coding-style, but it's not the preferred way to do so and unusual. It increases compilation and linking time.
Or can I put all the function (definitions) of my program in one .c file?
Yes, you can. Also again, matter of one's own coding-style.
If you got a lot or several functions in your code, you can also group the function definitions into own .c files and then link the files when invoking the compiler.
This way you keep clarity.
One way is also to keep all function definitions in a separate .c file, apart from main.c, which contains the main function.
Should I put each function in a .c and .h file?
Function definitions can't be placed inside of .h files.
.h consist only of function and other variable declarations, as well as macro definitions.
Function definitions need to be placed in .c files.
If you mean to place each function definition into an own .c file and each function declaration in an own .h, that definitely does not need to be either.
It even would confuse you all the way up.
You actually can do so, but it is definitely not recommended.
Or can I put all of the functions and headers in one .c and .h file ?
Again here you can't put function definitions in an .h file.
But you can pack all function definitions in one .c file and all function declarations in one .h file.
No! There is no need to do it at all. That would be affect your performance really badly.
Usually we only tend to create new files .h to store functions/methods that we want to use repeatedly in other projects or programs I guess.
Your program should be as follows:
Let's call this prog1.c
#include <only libs that you need>
void functionA (parameterType parameter){
//Whatever your function needs to do
}
int main(){
//this is your main function and where the program will start working.
functionA(parameters) /*Here is how you call functionA if it's void giving it's needed parameters.*/
}
Later on, with more knowledge you'll learn when you need to store or not the functions in others files to learn and keep it organized. There's no need for that now. You should focus the most on learning how they work and communicate with each other.
If you need to use functionA in other file, well then you will just need to include that .c file, like this:
In prog2.c you start it by calling out
#include "prog1.c"
I have 2 files: Sod/iload/iload.c and
Item/itemrule/itemrule.c, and I want to access a variable defined in iload.c which is defined in itemrule.c.
To do this, I made and defined a global variable in iload.c, and I tried to access this variable in itemrule .c with the extern keyword, but it is always 0.
I'm worried that it might be because the files have different paths, does anyone know how I can access this variable?
The usual idiom is to use an extern declaration in a header file and include that wherever the global is needed.
// foo.h
// Make the global visible in any C file that includes this header.
extern int my_global_var;
// foo.c
#include "foo.h" // Not really needed here, but fine.
int my_global_var;
...
// bar.c
#include <stdio.h>
#include "foo.h" // This one makes the global visible in the rest of the file.
void do_something(void) {
printf("my global var's value is: %d\n", my_global_var);
}
Note that using globals like this in a program of any significant size or complexity can lead to messy, bug-prone, and hard-to-change code. Not a great pattern to follow.
I would like to offer an alternative to Gene's answer. In my experience there are two main ways to share variables across modules (compilation units):
1) "Getters and Setters".
2) Externs.
Depending on what kind of team you're working with, they'll have a preference for one or the other. C functions by default have external linkage; you need to force internal linkage via the static keyword in front of the function name if you don't want this.
1) Getters and Setters:
// foo.c
#include <stdio.h>
int my_global_var = 0;
...
Then you can follow it with externally-linked getters and setters. i.e.:
int get_my_global_var(void)
{
return my_global_var;
}
void set_my_global_var(int var)
{
my_global_var = var;
}
This is done within the c file (module). It will be the getters and setters will be able to be called from any other module and they will get and set the global variable my_global_var.
2) Externs:
// foo.c
#include <stdio.h>
int my_global_var = 0;
...
An alternative to getters and setters is to use externs. In this case you add nothing extra to the module that contains the global variable you wish to access/modify (my_global_var).
// bar.c
#include <stdio.h>
extern int my_global_var;
...
Notice the syntax here; when we use the extern keyword, we don't initialize it as anything. We are simply infoming the compiler that the global variable my_global_var has external linkage.
So I'm following along in Head First C and we're on a chapter where we learn to compile multiple files together. One of them is encrypt.c.
#include "encrypt.h"
void encrypt(char *message)
{
char c;
while (*message) {
*message = *message ^ 31;
message++;
}
}
The encrypt.h file repeats the first line with a semicolon at the end, so why do I need it? I understand why I would need header files to fix the problem of using a function before it's defined, so I could understand #including it in a file that uses encrypt.c, but why would I need it inside encrypt.c? Is it just one of those "because" reasons?
If the contents of encrypt.c are shown in their entirety, then you don't need the header. But it's still a good idea to include it because:
If one function in the file uses another, then the order of definition matters because the callee must be defined before the caller. It's even possible to have two functions A and B where each calls the other, in which case you cannot get the code to compile without at least one forward declaration. Including the header with the forward declarations solves these problems.
Consuming the header just like your client code does is a good way to have the compiler point out discrepancies between the signatures in the forward declarations and the actual function definitions. If undetected this kind of problem can lead to "interesting" behavior at runtime and lots of hair-pulling.
You're right, if that's all encrypt.h declares, you don't need to include it in the .c file.
You mostly do it for consistency.
Imagine that you change encrypt.c to void encrypt(char *message, int i) { }
If you don't include encrypt.h you won't notice that the other files in your application haven't been updated to pass the new parameter. If you update encrypt.h and encrypt.c at the same time the compiler can do checking for you.
It's good style.
Sometimes, C-file with function implementation and C-file with function usage shares common declarations - types/structures, This shares declarations places at the H-file.
For ex.
[enc.h]
typedef enum {S,F} Res;
EN encode();
[enc.c]
#include "enc.h"
Res encode() { ... }
[other.c]
Res res;
res = encode();
It is prototyping the function
http://en.wikipedia.org/wiki/Function_prototype
Then you include the header in a another *.c-file the compiler knows in this way that anywhere else is the function definition.
This ist like:
#include <stdio.h>
int main (void)
{
afun();
return 0;
}
void afun (void)
{
printf("hello\n");
}
Now the compiler doesn't know what to do with afun() in the main function. Because it was'nt defined. So it will lead into an compiler error.
So you add the declaration at the beginning or bevore the first usage:
#include <stdio.h>
void afun(void);
int main (void)
{
afun();
return 0;
}
void afun (void)
{
printf("hello\n");
}
Know the compiler knows the deklaration of afun and hopes anythere else the function is defined. With header files it is possible to use precompiled c-code. The only thing the compiler is needed is the deklaration of the function.
I was told that a function defined as static in one .c file is not accessible from other files. But in the following program, I can access the static void show() function from another file. Is my understanding of static functions in C wrong?
a.h (first file):
static void show()
{
printf("I am in static show function in a.c");
}
b.c (another file):
#include"a.h"
void main()
{
show();
}
Remember that #includes work by copy-and-pasting the content of the included file. So in your example, after the #include has been processed, you get this:
static void show()
{
printf("I am in static show function in a.c");
}
void main()
{
show();
}
So clearly main can see show.1
The solution is to not #include .c files. In general, you should only #include header (.h) files. Your static functions shouldn't be declared or defined in the header file, so main will not be able to see it.
1. However, you now actually have two definitions of the show function, one in a.c and one in b.c. For static functions, this isn't a problem, but for non-static functions you would get a linker error.
static keyword changes the linkage specification to Internal Linkage.
A function marked as static will only be visible in that Translation Unit(TU).
Perhaps, You have same named symbols available in that particular TU, where you access the function. The how part of it can be only answered after you show us the code.
EDIT:
When you define a static function in header file, A copy of the same function gets created in every Translation Unit where you include it.Each instance of such a function is treated as a separate function(address of each function is different) and each instance of these functions have their own copies of static local variables & string literals.
Clearly, this will work but this might as well increase the size of your generated binary.
The other answers are correct, but it's not quite accurate to say that the static function is not accessible from another file. It is possible to access the function through a function pointer. It would be more accurate to say that the name of the function is not accessible in another translation unit.
Remember that converting C source code to an executable program consists of conceptual stages, including:
preprocessing (in which #include directives are replaced with the contents of the included file
compilation (which processes one translation unit at a time)
linking (in which the translation units are put together into the final program)
Suppose we have three files. foo.h:
typedef void (*void_function_p)(void);
extern void_function_p foo(void);
foo.c:
#include "foo.h"
#include <stdio.h>
static void baz(void) {
printf("worked!\n");
}
void_function_p foo(void) {
return baz;
}
bar.c:
#include "foo.h"
#include <stdio.h>
int main(void) {
(*foo())();
return 0;
}
This program compiles and prints "worked!" when it runs.
There are two translation units here. One is the code in the preprocessed foo.c (which, because of how #include works also includes the code in foo.h and stdio.h). The other is the code in the preprocessed bar.c (which, again, has its own copy of the code in foo.h and stdio.h).
By having the function foo return a pointer to the static function baz, we are able to call baz from the main function.
Now, consider what happens if we modify main to look like this:
int main(void) {
(*foo())();
baz();
return 0;
}
This code will result in a linker error because the name baz in this translation unit cannot be linked to the definition of baz in the other translation unit.
This is the first advantage of static functions: another programmer cannot accidentally access our baz function from another translation unit.
Now, consider what happens if we modify bar.c to look like this:
#include "foo.h"
#include <stdio.h>
static void baz(void) {
printf("still works!");
}
int main() {
(*foo())();
baz();
return 0;
}
This code will compile, and print "worked!" followed by "still works!"
This is the second advantage of static functions: we've defined two functions (in different translation units) with the same name.
If you try to put both static definitions in the same translation unit, you will get a compiler error about defining baz twice.
As a final note, if you take the program as it now stands and remove all the statics, it will result in a linker error because baz has been defined twice (with external linkage), which is not permitted.