C include error multiple definition error - c

I'm encountering a classic error but still don't get why it occurs...
Below is the simplified explanation
Apparently I have two C files main.c and support.c
in support.c i have one function void bla(int input);
in main.c i have several functions using bla from support.c, and i included
#include<support.c>
at the top of main.c
However I cannot compile the project because of the error multiple definition of bla, first defined here (eclipse points to the definition of bla in support.c)
I know that optimally I would have to create header file support.h and gives prototype extern void bla(int input) there, but for this I have to include the .c file.
Thanks in advance.

The preprocessor will copy the contents of support.c, and paste it to main.c to replace the line #include<support.c>. So there are two definition of the function bla, one in support.c, the other in main.c.
The solution is, don't include an source file. Put the declarations of functions that you want to export in a header file support.h, and include the header file in main.c:
#include "support.h"

You don't include source files into other source files. Instead you make a header file (with the extension .h) that contains declarations of functions, i.e. function prototypes. Then you build both source files separately, and link them together to form the final executable.
So a header file support.h like
#ifndef SUPPORT_H
#define SUPPORT_H
void blah(void);
#endif
(The preprocessor #ifdef/#define/#endif things are for include guards, to protect from multiple inclusion in the same source file.)
Then the support.c source file
#include "support.h"
void blah(void)
{
/* Some code here... */
}
And finally the main.c source file
#include "support.h"
int main(void)
{
blah();
return 0;
}
If you have an IDE (like Visual Studio) if you add these files to your project the IDE will make sure everything is built and linked properly. If you're compiling on the command line, compile each source file into an object file (usually using an option like -c (used for GCC and clang)) and then link the two object files together to create the executable.
Command line example with GCC:
$ gcc -Wall -c main.c -o main.o
$ gcc -Wall -c support.c -o support.o
$ gcc main.o support.o -o my_program
The above three commands will first compile the source files into object files, and then link them together.

What compiler are you using?
When compiling, make sure you do this:
gcc main.c support.c -o yourProgram

Related

Using a static library in c (.a file)

I am trying to create a static library using a shell script.
For creating the library I used following script:
gcc -c -Wall -Wextra -Werror *.c
ar -cr libft.a *.o
There are 5 different functions in 5 .c files.
Now I wanted to test the library and created a main.c file with this content:
#include "libft.a"
int main(void)
{
ft_putstr("hello");
}
Compiling the main.c (with gcc main.c) returns 419 warning and at least 20 errors looking something like this:
./libft.a:4:492: warning: null character ignored [-Wnull-character]
...<U+0000>UH<89><E5>H<83><EC><U+0010>#<88>}<FF><BF><U+0001><U+0000><U+0000><U+0000>H<8D>u...
Before this I was working with .h files which worked fine but this time I wasn't supposed to create a .h file so I don't what to do know.
#include "file_name" means like "please copy and paste the contents of the file file_name here", so it shouldn't be used with .a file.
You can write the declaration of the function to use directly instead of using .h file.
/* guessed from usage, please use correct argument and return type */
void ft_putstr(const char*);
int main(void)
{
ft_putstr("hello");
}
Then compile the source code with linking with the library:
gcc main.c -lft
When you compile your main.c, add the library name to it like this:
gcc main.c libft.a

Why I got "clang: error: cannot specify -o when generating multiple output files"?

I am a newbie in C. I have two simple source code files f1.c and f2.c.
f1.c looks like:
#include <stdio.h>
#include "f.h"
void f1(void) {
// some code ...
}
function f2() in f2.c relies on f1() in f1.c.
#include <stdio.h>
#include "f.h"
void f2(void) {
f1();
}
f1.c and f2.c share a same header f.h,
void f1(void);
void f2(void);
There are no main() access, I just want to compile these two file into a .o file without linker (using -c option),
gcc -c f1.c f2.c -o f2.o
then I got,
clang: error: cannot specify -o when generating multiple output files
but when I mentioned only f2.c, it works well,
gcc -c f2.c -o f2.o
So what's the problem? Thanks!
You should look into the compilation process for C. The first stage is compiling the .c source code into .o object files. The .c files do not need to see the other .c files; they are accepting as fact what you've told them about the existence of external functions. It's not until the linker comes in that it really needs to see the function because the implementation details don't matter to your .c file, just the interface, which you've presumably given it in the header.
What you can do, if you like, is drop the -o flag specifying the output file you want to create. Just compile with
gcc -c f1.c f2.c
and it will know to create f1.o and f2.o which will be able to link against each other when the time comes that you do want to go through with the linking process.
I am curious, however, what your intentions may be for wanting to compile these without linking. I only ask as you refer to yourself as a newbie, so I am wondering if maybe there is an end goal you have in mind and perhaps aren't asking the right question.

Using a function from another C file placed in another directory?

Say I have a parent directory A with two subdirectories B and C.
Sub-directory C has a helper.c and helper.h as shown:
//helper.c
void print(){
printf("Hello, World!\n");
}
//helper.h
void print();
Now, in sub directory B, I have a main.c which just calls the print function:
//main.c
#include<stdio.h>
#include"../C/helper.h"
void main(){
print();
}
I tried the following commands for compiling main.c:
Command 1: gcc main.c //Gives undefined reference to 'print' error
Command 2: gcc main.c ../C/helper.c //Compiles successfully
Now I removed the #include"../C/helper.h" from main .c and tried the Command 2 again. It still works.
So I have the following questions:
i) What difference does it make whether the helper.h file is included or
helper.c?
ii) Why command 1 fails?
iii) Is there a way to compile my C program without having to specify
helper.c everytime?
What happens when you execute:
Command 1: gcc main.c //Gives undefined reference to 'print' error
When execute gcc main.c
Compiler compiles main.c and creates objective file. This file will contain unresolved link to function print(). Because there is no implementation of function print() in main.c file.
After compilation gcc tries to make full executable file. To do this gcc combines all objective files and tries to resolve all unresolved links. As you remember there is unresolved link for function print(), gcc can't find implementation and raise the error.
When you execute
Command 2: gcc main.c ../C/helper.c //Compiles successfully
gcc compiles both files. Second file ../C/helper.c contains implementation of function print(), so linker can find it and resolve reference to it in function main().
i) What difference does it make whether the helper.h file is included or helper.c?
In your case helper.h contains forward declaration of function print(). This gives information to compiler how to make call of function print().
ii) Why command 1 fails?
See above.
iii) Is there a way to compile my C program without having to specify helper.c everytime?
Use make utility. Compile helper.c in separate objective file helper.o and use it in linkage command.
helper.o: ../C/helper.c ../C/helper.h
gcc -c ../C/helper.c
main.o: main.c main.h
gcc -c main.c
testprog: main.o helper.o
g++ main.o helper.o -o testprog
See make utility manual for details.
Commands should be indented by TAB.
First you need to understand that #include simply adds whatever text is in the #include parameter to the position in the file the statement is in, for example:
//file1.h
void foo();
//main.c
#include "file1.txt"
int main(int argc, char **argv)
{
foo();
return 0;
}
Will cause the pre-compilation to generate this unified file for compilation:
//main.c.tmp
void foo();
int main(int argc, char **argv)
{
foo();
return 0;
}
So to answer your first and second questions:
When you include a header file (or any file) that only contains declarations (i.e function signatures) without definitions (i.e function implementations), as in the example above, the linker will fail in finding the definitions and you will get the 'undefined reference' error.
When you include a c code file (or any file) that contains definitions, these definitions will be merged to your code and the linker will have them, that's why it works.
and as for your third question
It is bad practice to include c files directly in other c files, the common approach is to keep separate c files with headers exposing the functionality they provide, include the header files and link against the compiled c files, for example in your case:
gcc main.c helper.c -o out
Will allow you to include helper.c in main.c and still work because you instructed the compiler to compile both files instead of just main.c so when linking occurs the definitions from the compilation will be found and you will not get the undefined behavior error
This is, in a nutshell. I abstracted a lot of what's going on to pass on the general idea. this is a nice article describing the compilation process in fair detail and this is a nice overview of the entire process.
I'll try to answer:
i) What difference does it make whether the helper.h file is included or helper.c?
When you include a file, you don't want to expose your implementation, hence its better to include h files, that contains only the "signatures" - api of your implementation.
ii) Why command 1 fails?
When you compile you must add all your resources to the executable, otherwise he won't compile.
iii) Is there a way to compile my C program without having to specify
helper.c everytime?
You can use Makefile to compile your program. Maybe this tutorial can help you.
i) What difference does it make whether the helper.h file is included
or helper.c?
Including helper.c means that helper.c gets compiled each time as if it were part of main.c
Including helper.h lets the compiler know what argument types the function print() takes and returns so the compiler can give an error or warning if you call print() incorrectly
ii) Why command 1 fails?
The compiler is not being told where to find the actual code for the print function. As explained, including the .h file only helps the compiler with type checking.
iii) Is there a way to compile my C program without having to specify
helper.c everytime?
You can compile it once into an object file and optionally you can add that obj to a static or dynamically loaded library. You still need to help the compiler find that obj or library. For example,
gcc -c helper.c
gcc main.c helper.o
The correct way to avoid compiling modules that don't need compiling is to use a Makefile. A Makefile compares when a module was last compiled compared to when it was last modified and that way it knows what needs to be compiled and what doesn't.

How to use gcc correctly from the ubuntu terminal?

I'm try to compile a .c file from the terminal using gcc. The file includes a personal library where a function is defined. This library.h and the .c file are in the same directory.
I get the following message error
undefined reference to `function'"
Should I use another argument as:
gcc -o nameoutput filename
or should I place the library.h in another directory?
Assuming you have library.c, library.h and main.c in your current working directory:
$ gcc -Wall main.c library.c -o my_program
and then to run it:
$ ./my_program
"Undefined reference" means that the linker can't find the object file containing the compiled body of function; it doesn't have anything to do with the .h file.
I sounds like you have a situation where library.h and library.c are in one directory, and main.c is in a different directory. If that's the case, then your command line will need to look something like this:
gcc -o program -I /path/to/library main.c /path/to/library/library.c
-I /path/to/library means that gcc will look for .h files in that path as well as the standard include paths. That also allows you to write
#include "library.h"
instead of
#include "/path/to/library/library.h"
in any code that needs it.

How are you intended to include files in a C project?

I have three files.
trees.h
// a bunch of typedefs and function prototypes
#include <trees.c>
trees.c
// a bunch of function bodies
main.c
#include <trees.h>
This isn't right, because every function in trees.c is giving me "undefined type" errors about the type defined in trees.h. I've tried every configuration I can think of - include trees.c from main and include trees.h from trees.c, include trees.c at the end of trees.h, include it at the beginning of trees.h... Every combination of includes I could think of, and each one gives a different set of errors. Sometimes it's multiple defines, sometimes it's undefined functions...
So how exactly does this work? What do I put in which files, and which files do I include and where?
Like this:
trees.h
// a bunch of typedefs and function declarations (prototypes)
trees.c
#include <trees.h>
// a bunch of function definitions (bodies)
main.c
#include <trees.h>
Explanation:
#include is basically the same as copying the entire included file to this file (where you put the #include).
So including trees.h in main.c allows that file to know about functions in trees.c.
Including trees.h in trees.c allows functions lower down in trees.c to be usable and this is also where defines, etc. used in trees.c is specified.
You also may not know about creating multiple objects and linking them, refer to Joachim Pileborg's answer.
The (very ugly) alternative is:
trees.h
// a bunch of typedefs and function declarations (prototypes)
trees.c
#include <trees.h>
// a bunch of function definitions (bodies)
main.c
#include <trees.c>
Then you just need to compile main. But for any project of a few .c files, this becomes impractical.
You compile each source file into object files, then link these object files together to form the final executable. If you use e.g. GCC and compile on the command line you can put both source files in the command line and GCC will handle it for you:
$ gcc main.c tree.c -o tree
The above command tells gcc to compile and link the files main.c and tree.c, and name the output executable tree. You can also compile the source file separately into object files, and then manually link them together:
$ gcc -c main.c -o main.o
$ gcc -c tree.c -o tree.o
$ gcc main.o tree.o -o tree
In the above commands, the -c option tells gcc to create an object file, and the -o option tells gcc what to name that object file. The last command takes these object files and create the final executable and names it (with the -o option) tree.
In the source files, you include the header(s) needed, not the other way around.
The reason it's not working is because you have to use 'extern' to define a variable or function that is declared in a different include file to the standard ones. You should also save all header files as *.h. So, assuming you had defined the struct 'tree' in tree.h:
#include <tree.h>
int main() {
extern tree; /* Get variable 'tree' declared in tree.h */
extern make_tree(void); /* Get function make_tree() declared in tree.h */
make_tree(); /* Call function */
return (0); /* End */
}
Begin with not including implementation (.c) files. Only include header (.h) files. Include them whenever you need the types or functions declared in them. To avoid multiple declarations, use include guards (whatever they are - just google it).
The way to go is including your header file trees.h in trees.c and then including trees.c within main.c
Have a look at this thread here

Resources