I have a header file command.h which contains all my variables and function declarations
//command.h
int someVar1;
int someVar2;
void modifying_loop (int a, int b);
int someVar3;
.
.
.
In another file my_algorithm.c I define the previously declared function modifying_loop and use some of the variables declared in the header in
//my_algorithm.c
#include "command.h"
void modifying_loop (int x, int y)
{
someVar1 = x+2;
someVar2 = y+2;
}
And I have my main file command.c I called the modifying_loop function like this :
#include "command.h"
int main ()
{
modifying_loop(5,6);
return 0;
}
I compile the it using gcc -o command command.c -lm -lpigpio -L/usr/lib/ which returns me
undefined reference to modifying_loop'
Then to tackle that I link the my_algorithm.c file by using
gcc -o command command.c my_algorithm.c -lm -lpigpio -L/usr/lib/ which gives me the following :
/usr/bin/ld: /tmp/cc6ad5oo.o:(.bss+0x3c18): multiple definition of `someVar1'; /tmp/ccaydPyq.o:(.bss+0x24918): first defined here
/usr/bin/ld: /tmp/cc6ad5oo.o:(.bss+0x3c1c): multiple definition of `someVar2'; /tmp/ccaydPyq.o:(.bss+0x2491c): first defined here
and same errors for the rest of the variables declared in the header file. Does anyone have any idea what is causing the errors.
/usr/bin/ld: /tmp/cc6ad5oo.o:(.bss+0x3c18): multiple definition of `someVar1'; /tmp/ccaydPyq.o:(.bss+0x24918): first defined here
/usr/bin/ld: /tmp/cc6ad5oo.o:(.bss+0x3c1c): multiple definition of `someVar2'; /tmp/ccaydPyq.o:(.bss+0x2491c): first defined here
you have to make sure, the same code won't be included multiple times.
You can do this by embedding the header file code in #ifndef #define #endif macros. These are called include guards
The rest of your code seems to be working fine.
Related
I'm a beginner learning c. I know that use of word "static" makes a c function and variable local to the source file it's declared in. But consider the following...
test.h
static int n = 2;
static void f(){
printf("%d", n);
}
main.c
#include <stdio.h>
#include "test.h"
int main()
{
printf("%d", n);
f();
return 0;
}
My expected result was that an error message will throw up, since the function f and variable n is local to test.h only? Thanks.
But instead, the output was
2
2
EDIT:
If it only works for a compilation unit, what does that mean? And how do I use static the way I intended to?
static makes your function/variable local to the compilation unit, ie the whole set of source code that is read when you compile a single .c file.
#includeing a .h file is a bit like copy/paste-ing the content of this header file in your .c file. Thus, n and f in your example are considered local to your main.c compilation unit.
Example
module.h
#ifndef MODULE_H
#define MODULE_H
int fnct(void);
#endif /* MODULE_H */
module.c
#include "module.h"
static
int
detail(void)
{
return 2;
}
int
fnct(void)
{
return 3+detail();
}
main.c
#include <stdio.h>
#include "module.h"
int
main(void)
{
printf("fnct() gives %d\n", fnct());
/* printf("detail() gives %d\n", detail()); */
/* detail cannot be called because:
. it was not declared
(rejected at compilation, or at least a warning)
. even if it were, it is static to the module.c compilation unit
(rejected at link)
*/
return 0;
}
build (compile each .c then link)
gcc -c module.c
gcc -c main.c
gcc -o prog module.o main.o
You have included test.h in main.c.
Therefore static int n and static void f() will be visible inside main.c also.
When a variable or function is declared at file scope (not inside any other { } brace pair), and they are declared static, they are local to the translation unit they reside in.
Translation unit is a formal term in C and it's slightly different from a file. A translation unit is a single c file and all the h files it includes.
So in your case, the static variable is local to the translation unit consisting of test.h and main.c. You will be able to access it in main.c, but not in foo.c.
Meaning that if you have another .c file including test.h, you'll get two instances of the same variable, with the same name. That in turn can lead to all manner of crazy bugs.
This is one of many reasons why we never define variables inside header files.
(To avoid spaghetti program design, we should not declare variables in headers either, unless they are const qualified.)
I've these simple source files:
Header file
//header.h
#ifndef HEADER_H
#define HEADER_H
#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>
#include <stdint.h>
#include <string.h>
void test_uint_to_mpz();
#endif
Implementation file
//src.c
#include "header.h"
void test_uint_to_mpz() {
char hex_string[200];
uint64_t var;
mpz_t mpz_var;
mpz_init(mpz_var);
printf("Please enter a hex string that fits a variable uint64_t : ");
scanf("%s",hex_string);
var = (uint64_t)strtol(hex_string,NULL,16);
mpz_set_ui(mpz_var,var);
printf("Your input value was: %llx\n",var);
printf("The mpz equivalent is: ");
mpz_out_str(stdout,16,mpz_var);
printf("\n");
mpz_clear(mpz_var);
}
Main
//main.c
#include "header.h"
int main(int argc, char** argv) {
test_uint_to_mpz();
return 0;
}
Then I try to compile using this simple line:
gcc src.c main.c -L/user/lcg/lib -o numericalTest -I./ -lgmp -O3 -static
Since I want to use a static linking. To me is fine, I'm quite sure that the installation of gmp is fine (see the -L option in my command line).
However then I have:
gcc src.c main.c -L/user/lcg/lib -o numericalTest -I./ -lgmp -O3 -static
/tmp/ccz2qa8j.o: In function `__gmpz_abs':
main.c:(.text+0x0): multiple definition of `__gmpz_abs'
/tmp/cc0jVOgJ.o:src.c:(.text+0x0): first defined here
/tmp/ccz2qa8j.o: In function `__gmpz_fits_uint_p':
main.c:(.text+0x20): multiple definition of `__gmpz_fits_uint_p'
/tmp/cc0jVOgJ.o:src.c:(.text+0x20): first defined here
/tmp/ccz2qa8j.o: In function `__gmpz_fits_ulong_p':
main.c:(.text+0x60): multiple definition of `__gmpz_fits_ulong_p'
/tmp/cc0jVOgJ.o:src.c:(.text+0x60): first defined here
/tmp/ccz2qa8j.o: In function `__gmpz_fits_ushort_p':
main.c:(.text+0x70): multiple definition of `__gmpz_fits_ushort_p'
/tmp/cc0jVOgJ.o:src.c:(.text+0x70): first defined here
/tmp/ccz2qa8j.o: In function `__gmpz_get_ui':
main.c:(.text+0xb0): multiple definition of `__gmpz_get_ui'
/tmp/cc0jVOgJ.o:src.c:(.text+0xb0): first defined here
/tmp/ccz2qa8j.o: In function `__gmpz_getlimbn':
main.c:(.text+0xd0): multiple definition of `__gmpz_getlimbn'
/tmp/cc0jVOgJ.o:src.c:(.text+0xd0): first defined here
/tmp/ccz2qa8j.o: In function `__gmpz_neg':
main.c:(.text+0x110): multiple definition of `__gmpz_neg'
/tmp/cc0jVOgJ.o:src.c:(.text+0x110): first defined here
/tmp/ccz2qa8j.o: In function `__gmpz_perfect_square_p':
main.c:(.text+0x130): multiple definition of `__gmpz_perfect_square_p'
/tmp/cc0jVOgJ.o:src.c:(.text+0x130): first defined here
/tmp/ccz2qa8j.o: In function `__gmpz_popcount':
main.c:(.text+0x150): multiple definition of `__gmpz_popcount'
/tmp/cc0jVOgJ.o:src.c:(.text+0x150): first defined here
/tmp/ccz2qa8j.o: In function `__gmpz_set_q':
main.c:(.text+0x180): multiple definition of `__gmpz_set_q'
/tmp/cc0jVOgJ.o:src.c:(.text+0x180): first defined here
/tmp/ccz2qa8j.o: In function `__gmpz_size':
main.c:(.text+0x190): multiple definition of `__gmpz_size'
/tmp/cc0jVOgJ.o:src.c:(.text+0x190): first defined here
/tmp/ccz2qa8j.o: In function `__gmpq_abs':
main.c:(.text+0x1a0): multiple definition of `__gmpq_abs'
/tmp/cc0jVOgJ.o:src.c:(.text+0x1a0): first defined here
/tmp/ccz2qa8j.o: In function `__gmpq_neg':
main.c:(.text+0x1c0): multiple definition of `__gmpq_neg'
/tmp/cc0jVOgJ.o:src.c:(.text+0x1c0): first defined here
/tmp/ccz2qa8j.o: In function `__gmpn_add':
main.c:(.text+0x1e0): multiple definition of `__gmpn_add'
/tmp/cc0jVOgJ.o:src.c:(.text+0x1e0): first defined here
/tmp/ccz2qa8j.o: In function `__gmpn_add_1':
main.c:(.text+0x360): multiple definition of `__gmpn_add_1'
/tmp/cc0jVOgJ.o:src.c:(.text+0x360): first defined here
/tmp/ccz2qa8j.o: In function `__gmpn_cmp':
main.c:(.text+0x570): multiple definition of `__gmpn_cmp'
/tmp/cc0jVOgJ.o:src.c:(.text+0x570): first defined here
/tmp/ccz2qa8j.o: In function `__gmpn_sub':
main.c:(.text+0x5a0): multiple definition of `__gmpn_sub'
/tmp/cc0jVOgJ.o:src.c:(.text+0x5a0): first defined here
/tmp/ccz2qa8j.o: In function `__gmpn_sub_1':
main.c:(.text+0x720): multiple definition of `__gmpn_sub_1'
/tmp/cc0jVOgJ.o:src.c:(.text+0x720): first defined here
collect2: error: ld returned 1 exit status
make: *** [output] Error 1
Where could be the problem?
Update: i post the makefile
CC=gcc
SRCS=src.c main.c
HEADER=header.h
OBJ_FILES=$(addsuffix ./,(basename $(SRCS)))
INCLUDES=-I./
FLAG=-lgmp -O3
output : $(SRCS) $(HEADER)
$(CC) $(SRCS) -L/user/lcg/lib -o numericalTest $(INCLUDES) $(FLAG) -static
clean :
rm *.o
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.
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.
I declared a variable i in temp2.h
extern i; which contains just one above line
and made another file
temp3.c
#include<stdio.h>
#include<temp2.h>
int main ()
{
extern i;
i=6;
printf("The i is %d",i);
}
When I compiled above as
cc -I ./ temp3.c I got following errors
/tmp/ccJcwZyy.o: In function `main':
temp3.c:(.text+0x6): undefined reference to `i'
temp3.c:(.text+0x10): undefined reference to `i'
collect2: ld returned 1 exit status
I had declared extern in temp3.c above as K R page 33 says as I mentioned in above post.
I tried another way for temp3.c with same header file temp2.h
#include<stdio.h>
#include<temp2.h>
int main ()
{
i=6;
printf("The i is %d",i);
}
and compiled it cc -I ./ temp3.c and got following error
/tmp/ccZZyGsL.o: In function `main':
temp3.c:(.text+0x6): undefined reference to `i'
temp3.c:(.text+0x10): undefined reference to `i'
collect2: ld returned 1 exit status
I also tried
#include<stdio.h>
#include<temp2.h>
int main ()
{
extern i=6;
printf("The i is %d",i);
}
compiled this one
cc -I ./ temp3.c
got same error as in post 1
temp3.c: In function ‘main’:
temp3.c:5: error: ‘i’ has both ‘extern’ and initializer
So I have tried at least 3 different ways to use extern but non of them worked.
When you declare a variable using extern , you are telling the compiler that the variable was defined elsewhere and the definition will be provided at the time of linking. Inclusion is a different thing altogether.
extern
An external variable must be defined, exactly once, outside of any function; this sets aside storage for it. The variable must also be declared in each function that wants to access it; this states the type of the variable. The declaration may be an explicit extern statement or may be implicit from context.
-The C Programming Language
A variable must be defined once in one of the modules(in one of the Translation Units) of the program. If there is no definition or more than one, an error is produced, possibly in the linking stage (as in example 1 and 2).
Try something like the following
a.c
int i =10; //definition
b.c
extern int i; //declaration
int main()
{
printf("%d",i);
}
Compile, link and create an executable using
gcc a.c b.c -o executable_name
or
gcc -c a.c // creates a.o
gcc -c b.c // creates b.o
Now link the object files and create an executable
gcc a.o b.o -o executable_name
extern is declaration mechanism used to tell the compiler that the variable is defined in another file.
My Suggestion is that you define a variable in a ".c" file and then add the extern declaration in the corresponding ".h" file. In this way, the variable declaration will be available to all the source files which includes this header file and also it will be easier for one to identify in which ".c" it is actually defined.
The first program said:
The variable i (implicitly of type int) is defined somewhere else - but you didn't define it anywhere.
The second program tried to use a variable for which there was no declaration at all.
The third program tried to declare a variable without an explicit type (used to be OK; not allowed in C99), and said:
The variable i is defined somewhere else, but I want to initialize it here.
You are not allowed to do that.
So, the compiler is correct in all cases.
The declaration in the header 'temp2.h' should be fixed to extern int i; first. The implicit int is long obsolete.
You could fix the first example in several ways:
#include <stdio.h>
#include <temp2.h>
int main()
{
extern int i;
i=6;
printf("The i is %d",i);
return 0;
}
int i;
This defines the variable after the function - aconventional but legitimate. It could alternatively be in a separate source file that is separately compiled and then linked with the main program.
The second example could be fixed with:
#include <stdio.h>
#include <temp2.h>
int main()
{
int i=6;
printf("The i is %d",i);
return 0;
}
It is important to note that this example now has two variables called i; the one declared in temp2.h (but not actually referenced anywhere), and the one defined in main(). Another way of fixing it is the same as in the first possible fix:
#include <stdio.h>
#include <temp2.h>
int main()
{
i=6;
printf("The i is %d",i);
return 0;
}
int i;
Again, aconventional placement, but legitimate.
The third one can be fixed by similar methods to the first two, or this variant:
#include <stdio.h>
#include <temp2.h>
int i;
int main()
{
extern int i;
i=6;
printf("The i is %d",i);
return 0;
}
This still declares i in <temp2.h> but defines it in the source file containing main() (conventionally placed - at the top of the file). The extern int i; insides main() is doubly redundant - the definition in the source file and the declaration in the header mean that it does not need to be redeclared inside main(). Note that in general, the declaration in the header and the definition in the source file are not redundant; the declaration in the header provides a consistency check with the definition, and the other files that also use the variable and the header are then assured that the definition in the file containing main() is equivalent to the definition that the other file is using too.