I am having some trouble compiling a few files using headers. Here is a breakdown of my code:
file1.c
#include "header.h"
int main() {
func1();
return 0;
}
file2.c
#include "header.h"
void func1() {
... function implementation ...
}
header.h
void func1();
The error I am getting is:
In function 'main':
undefined reference to 'func1'
Note: I am just using a simple breakdown of how my 3 files are set up. I need to get this to work with the 3 files. I am setting/including everything properly? I need to use this set up, but I am just unsure how file.c gets reference to the actually implementation of func1().
If the error is an undefined reference to func1(), and there is no other error, then I would think it's because you have two files called header.h in your project and the other copy is being included instead of your copy with the declaration of func1().
I would check the include paths for your project and make sure that the header.h with your declaration of func1() is being included first.
Related
If I have a project with the following 3 files in the same directory:
mylib.h:
int some_global;
void set_some_global(int value);
mylib.c:
#include "mylib.h"
void set_some_global(int value)
{
some_global = value;
}
main.c:
#include <stdio.h>
#include "mylib.h"
int main()
{
set_some_global(42);
printf("Some global: %d\n", some_global);
return 0;
}
and I compile with
gcc main.c mylib.c -o prog -Wall -Wpedantic
I get no errors or warnings, and the prog program prints 42 to the console.
When I first tried this, I expected there to be a "multiple definition" error or some kind of warning since some_global is not declared extern in the header file. Upon researching this issue, I discovered that in C the extern is implicit on variable declarations outside of functions (and also that the opposite is true for C++, which can be demonstrated by using g++ instead of gcc in the compilation line above). Also, if I change the line in mylib.h from a declaration to a definition (e.g. int some_global = 1;), I do get the "multiple definition" error that I expected (this is nothing shocking).
My main question is: where is the variable being defined? It appears to be implicitly defined somewhere, but at what point does either the compiler or linker realize it needs that variable defined and does so?
Also, why is it that if I explicitly declare the variable as extern in the mylib.h file, I get "undefined reference" errors unless I explicitly declare the variable in one and only one *.c? I would expect that given the reason why the code above works (that extern is implicit), that explicitly declaring extern wouldn't make a difference. Why is there a difference in behavior?
Follow up
After the answer below corrected me that the code in mylib.h is a "tentative definition" rather than a declaration, I discovered this related answer with more details on such matters:
https://stackoverflow.com/a/3095957/7007605
Your code compiles and links without error only because you use gcc which was compiled with -fcommon command line option "The -fcommon places uninitialized global variables in a common block. This allows the linker to resolve all tentative definitions of the same variable in different compilation units to the same object, or to a non-tentative definition. (...) It is mainly useful to enable legacy code to link without errors." This was default prior to version 10, but even now many toolchains are still build with this option enabled.
Never define data in the header files. Place only extern definitions of the variables in the header files.
It should be:
extern int some_global;
void set_some_global(int value);
mylib.c:
#include "mylib.h"
int some_global;
void set_some_global(int value)
{
some_global = value;
}
main.c:
#include <stdio.h>
#include "mylib.h"
int main()
{
set_some_global(42);
printf("Some global: %d\n", some_global);
return 0;
}
int some_global; is a tentative definition. In GCC before version 10, GCC produced an object file treating this as a common symbol. (This behavior is still selectable by a switch, -fcommon.) The linker coalesces multiple definitions of a common symbol to a single definition.
I declared a global static function in one file
a.c
static void Func1(void);
void Func2(void);
void Func1(void) {
puts("Func1 Called");
}
void Func2(void) {
puts("Func2 Called");
}
and accessed it in b.c
#include <stdio.h>
#include "a.c"
void main() {
Func1();
Func2();
}
the program complied successfully, but as per provided information this should give error: undefined reference to Func1. What wrong is happening here?
You don't include a source file in another, you compile and link them together.
In you case, by saying #include "a.c", you're essentially putting the whole content of a.c into b.c and then starting the compilation, so the static functions and their calls are present in the same translation unit. Thus, there is no issue for compiler to find the called function.
Instead, if you do something like
gcc a.c b.c -o a.out //try to compile and link together
you'll see the expected error, as in this case, a.c and b.c will be two separate translation units.
You declare in header files and define in .c files. So you must use header files to represent the variables or functions you defined. Instead if you use .c files then it leads to multiple definitions.I think that is why you can access that global function.
I have this folder structure:
I wrote a simple function to test the folder structure, for seen if all header file but when I compile with the make command, I have this error:
warning: function 'stampa' has internal linkage but is not defined
I the lagrange.h file I have this:
#ifndef LAGRANGE_H
static void stampa(int i);
#endif /* LAGRANGE_H */
and in the lagrange.c file I have this:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <stdio.h>
void stampa(int i){
printf("%d", i);
}
in the end, int main.c I simply call the function stampa passing them a number.
Explanation of the error:
The compilation error occurs because:
You have declared a function with static keyword (i.e. with internal linkage) inside lagrange.h
And you have included this file lagrange.h in main.c file different from lagrange.c, where the function is not defined.
So when the compiler compiles main.c file, it encounters the static declaration without any associated definition, and raises logically the error. The error message is explicit.
Solution:
In your case the solution is to remove the static keyword, because static means that the function can be called only in the .c file where it is defined, which is not your case.
Moreover, a good practice may be to declare any static function in the same .c file where it is defined, and not in .h file.
Coming up with errors for undefined references in main.c. This is because I have several files in this fashion:
main.c
{
#include "somefile.h"
somfunct() <--- undefined reference error
}
somefile.h
{
somefunct() declaration
...
}
somefile.c
{
#include "somefile.h"
somefunct() definition
...
}
I am trying to use proper organization in that I use only declarations in the header files and define them in a separate file. After splitting up my code I get the undefined reference error because there is no link between somefile.h and somefile.c. Even though main.c includes the somefile.h header file, there is nothing in somefile.h that explicitly mentions somefile.c, so my functions are only partially defined. What is the proper way to take care of this problem? Many thanks. I hope this is clear let me know if not.
Here's a complete and working example of your goal.
main.c
#include "somefile.h"
int main() {
somefunc();
return 0;
}
somefile.h
#ifndef RHURAC_SOMEFILE_H
#define RHURAC_SOMEFILE_H
void somefunc();
#endif
somefile.c
#include <stdio.h>
#include "somefile.h"
void somefunc() {
printf("hello\n");
}
example build ( gcc )
gcc main.c somefile.c -o main
output
$ ./main
hello
I have two source files:
Source FIle 1 (assembler.c):
#include "parser.c"
int main() {
parse_file("test.txt");
return 0;
}
Source File 2 (parser.c):
void parse_file(char *config_file);
void parse_file(char *src_file) {
// Function here
}
For some reason, when compiling it is giving me the following error:
duplicate symbol _parse_file in ./parser.o and ./assembler.o for architecture x86_64
Why is it giving me a duplicate symbol for parse_file? I am just calling the function here... No?
First off, including source files is a bad practice in C programming. Normally, the current translation unit should consist of one source file and a number of included header files.
What happens in your case is that you have two copies of the parse_file function, one in each translation unit. When parser.c is compiled to an object file, it has its own parse_file function, and assembler.c also has its own.
It is the linker that complains (not the compiler) when given two object files as an input, each of which contains its own definition of parse_file.
You should restructure your project like this:
parser.h
void parse_file(char *);
parser.c
void parse_file(char *src_file) {
// Function here
}
assembler.c
/* note that the header file is included here */
#include "parser.h"
int main (void) {
parse_file("test.txt");
return 0;
}
You're including the parser.c file, which means all the code that is in that file will be "copied" to assembler.c file. That means that the entire contents of parser.c will be compiled when the compiler is compiling parser.c, and then it'll be compiled again when the compiler is compiling assembler.c
That's what headers are for.
In the header you can put only the declarations, so you can include it without creating the same symbols again in a different translation unit.
so you can just create a parser.h containing just the declaration of the function:
void parse_file(char *config_file);
then in your assembler.c you include just the header:
#include "parser.h" //include the header, not the implementation
int main() {
parse_file("test.txt");
return 0;
}
You are including the .c file which contains the definition of the function parse_file. Thus it is defined twice, once in each translation unit, which is not allowed.
As other answers state, including the source means the file will be copied to parser.c and will be defined there as well in the original place (assembler.c). To solve this, either create a header file with your prototype:
parser.h
void parse_file(char *config_file);
And include that file:
assembler.c
#include "parser.h"
int main() {
parse_file("test.txt");
return 0;
}
Or remove the include and provide a clue to the function:
int main() {
void parse_file(char *);
parse_file("test.txt");
return 0;
}
Or even simply remove the include at al. Not good practice, as the compiler (without information on a function) will consider its returned value is an integer and may cause other warnings.