defining a function twice in C - c

i have a problem. i wrote this code, a.h. a.c and the main.c:
file: a.h
#ifndef _a_H
#define _a_H
int poly (int a, int b, int c, int x);
int square (int x)
{
return x*x;
}
#endif // _a_H
file: a.c
#include "a.h"
int poly (int a, int b, int c, int x)
{
return a*square(x) + b * x +c;
}
file: main.c
#include <stdio.h>
#include "a.h"
int main()
{
int p1 = poly1 (1 ,2 , 1, 5);
int p2 = poly2 (1 ,1 , 3, 5);
printf ("p1 = %d, p2 = %d\n", p1, p2);
return 0;
}
and i got an error:
/tmp/ccKKrQ7u.o: In function 'square':
main.c:(.text+0x0): multiple definition of 'square'
/tmp/ccwJoxlY.o:a.c:(.text+0x0): first defined here
collect2: ld returned 1 exit status
so i moved the implementation of the function square to the a.c file and it works.
does any one know why?
thanx

Generally speaking, *.c files are compiled into *.o files, and *.o files are linked to build the executable. *.h files aren't compiled, they are included textually in the *.c files, at the point they are #included.
So by #including "a.h" twice, in two separate *.c files, you've placed your definition for square() into two separate files. When these are compiled, you end up with two copies of square(), one in each *.o file. Then when you link them, the linker sees the two files, and generates an error.
How to avoid this? You've already discovered this. Don't put function definitions in *.h files. Put them in *.c files, and only put the function declarations in the *.h files.

Don't put code in your header files. Both of your .c files include a.h, so both of them get an implementation of square, so your linker complains.

When square() was in the header, it was included in both a.c and main.c, so each of the corresponding object files had its own square(), but without the static modifier, they had the exact same name. Moving it to a.c means that it's only defined once.
If you really want the function in the header file, you can define it with static inline thus:
static inline int square (int x)
{
return x*x;
}
Static will mean that each .c file that includes the .h will have its own version of square(), inline means that the code will be dropped inline, and no function call will actually happen, which is probably what you want here

This happens because your C compiler builds each .c file into an object (.o) file, and then links the object files to make the executable. The contents of a .c file and all the files it includes are known as a compilation unit.
Your example has two compilation units:
main.c, including stdio.h and a.h → compiles to main.o
a.c, including a.h → compiles to a.o
The linker (ld) then attempts to link the .o files but finds they both define square(), because it was in the shared a.h — hence the error. This is why, as some have already pointed out, you should not put function definitions in headers.
If you have the nm utility installed (which you should have), you can run
$ nm main.o
$ nm a.o
in the shell to see that square exists in both files.
(Edit: The term I was thinking of was actually translation unit, but on searching around they seem to mean pretty much the same thing.)

You can't write an implementation (function body) in a header file, otherwise the linker will find more than one reference to that function.
As a rule, put only declarations in header files, not definitions.

You've answered your own question: you've defined square twice, once in each compiled file that includes a.h.
To avoid this you can make square a static function
static int square (int x)
{
return x*x;
}
and add whichever inline hint your compiler uses, e.g. inline or __inline too.

Related

Why static global variable is accessible in other file?

//a.c
#include <stdio.h>
#include "b.c"
void main()
{
int var;
var = increment();
var = increment();
var = increment();
count = count + 3;
var = count;
printf("%d", var);
}
//b.c
static int count;
int increment()
{
++count;
return count;
}
Now as in b.c file I have a variable with name count and is static. Now this variable should not be accessible in a.c directly but in my case I can access and manipulate it. So am I missing something?
OUTPUT
6
#include "b.c" in a.c makes b.c a part of the compilation of a.c; they are compiled as one source file.
To keep identifiers in separate source files separate, you compile them separately, without using #include to include one in the other. The separate compilations produce separate object files (.o files on Unix and Unix-like systems), which you then link together with a link command (which may be included in or performed by the gcc command).
Separating the source files also separates an identifier you do want to share between the two files, the function named increment. So a.c will not know about increment, and the compiler will complain. To deal with this for a single function, you can simply declare the function in a.c with extern int increment();. However, the usual technique for managing this sharing of identifiers is:
Create a file named b.h that declares identifiers to be defined in b.c but shared with other source files.
In b.h, declare increment with extern int increment();.
In any source file that will use identifiers from b.c, include b.h with #include "b.h".
In b.c, also include b.h. This provides a check that the declarations in b.h match the definitions in b.c, because the compiler will see both while compiling b.c and report inconsistencies.
You've included b.c in a.c, so they become a single unit as far as the compiler is concerned. Because of this, you can see the static variable.
If you removed the include line, you wouldn't see either count or increment, although the latter would be implicitly declared because it is a function.

Use of modifier static in c

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.)

Call external function written in C from another file written in C in a Linux enviroment

I am having trouble calling an external function I wrote in the Pico editor in linux. The program should call an external function and they are both written in C.
#include????
void calcTax()
float calcfed()
float calcssi()
// stub program
#include"FILE2"???or do I use"./FILE2"// not sure which to use here or what extension the file should have. .c or .h and if it is .h do I simply change the file name to file.h?
#include<stdio.h>
#define ADDR(var) &var
extern void calctaxes()
int main()
{
}
I am using gcc to compile but it will not compile. both files are in the same directory and have the .c extension
I am a new student so bear with me.
Normally, when you want a function in one compilation unit to call a function in another compilation unit, you should create a header file containing the function prototypes. The header file can be included in both compilation units to make sure that both sides agree on the interface.
calctax.h
#ifndef calctax_h_included
#define calctax_h_included
void calctaxes(void);
/* any other related prototypes we want to include in this header */
#endif
Note that extern is not required on functions, only global data. Also, since the function takes no arguments, you should put void in the argument list, and you also need a semi-colon at the end of the prototype.
Next, we can include this header file in the .c file that implements the function:
calctax.c
#include "calctax.h"
void calctaxes(void)
{
/* implementation */
}
Finally, we include the same header file in our main .c file that calls the function:
main.c
#include "calctax.h"
int main(int argc, char **argc)
{
calctax();
return 0;
}
You can compile and link these together with
% gcc -o main main.c calctax.c
Normally you don't want to include .c implementation files. The normal thing to do is have two source files that you build into objects:
cc -o file1.o file1.c
cc -o file2.o file2.c
And then link them into an executable at the end:
cc -o example file1.o file2.o
To allow calling functions between the two .c files, you create a header (.h) file that has function declarations for everything you're interested in sharing. For you, that might be something like header.h, containing:
void calcTax(void);
float calcfed(void);
float calcssi(void);
Then, just #include "header.h" from the implementation files where you need to know about those functions.

#include other C programs

I need to include file_1.c into main.c. In file_1.c, I currently have multiple functions. If I want to call these functions in main.c, what do I need to do? I have #include"file_1.c" in my main program.
Use standard approach by making header file
#include"file_1.h"
you will have to compile this "file_1.c" together with main.c and make one executable
because function calls are need in run time.
Try this :
create a header file file_1.h
#ifndef _FILE_H
#define _FILE_H
void foo(int );
#endif
give all the declaraion of function and struct definitions (if any) or any global variables
then in file_1.c will contain actual defintion of function
//file_1.c
#include "file_1.h"
#include <stdio.h>
void foo(int x)
{
printf("%d\t",x);
}
//main.c
#include "file_1.h"
int main()
{
int x=10;
foo(x);
return 0;
}
include header file file_1.h in both (main.c and file_1.c) the c files
In gcc
gcc -Wall main.c file_1.c -o myexe.out
Why do you think you need to do this?
Normally you would add the declaration of functions in file_1.c into file_1.h and include that in main.c.
When you link the program, you just need to include both main.c and file_1.c (which then includes the definitions of the functions) on the command line.

Duplicate Symbol in C

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.

Resources