Linker error inline function - c

I got some compiler/linker errors and i don't know what is the correct method to proceed. I'm in this situation:
a.h: in this file is defined a function declared as "inline", for example: inline void foo1();
b.h: in this file is defined a function declared as "inline" that calls foo1(): inline void foo2();
main.c: there are some functions calls of both foo1 and foo2().
Now, if i declare foo1 and foo2 in a.h and b.h as extern inline void i got the following error:
prj/src/b.o: In function foo1': (.text+0x0):
multiple definition offoo1'
prj/src/main.o:(.text+0x0): first defined here make: *
[kernel] Error 1
What is the way which allow to compile and link without errors/warning in the situation i described?

From http://gcc.gnu.org/onlinedocs/gcc/Inline.html:
When an inline function is not static, then the compiler must assume
that there may be calls from other source files; since a global symbol
can be defined only once in any program, the function must not be
defined in the other source files, so the calls therein cannot be
integrated. Therefore, a non-static inline function is always compiled
on its own in the usual fashion.
In other words, without static, it emits a symbol for your inline function. If you happen to define that function in a header and include it in more than one compilation unit, then you end up with multiple (redefined) symbols. If you want to include the definition in the header, you should make it static.

I tried it and didn't get any errors
a.h
extern inline void foo1()
{
return;
}
b.h
extern inline void foo2()
{
foo1();
return;
}
main.cpp
#include "a.h"
#include "b.h"
int main() {
foo1();
foo2();
return 0;
}

Put the inline definitions in your .h file and in the .c files force an external definition.
For example:
// File: a.h
inline void foo1(void) { /*...*/ }
// File main.c
#include "a.h"
extern inline void foo1(void);
int main(void)
{
/*...*/
}

You may consider using header guards to prevent redefinition. The implementation of the files is as follows. I tried compilation for the following files using CMake and it worked without any problem.
a.h
#ifndef A_H
#define A_H
inline
void foo1()
{
return;
}
#endif
b.h
#ifndef B_H
#define B_H
#include "a.h"
inline
void foo2()
{
foo1();
return;
}
#endif
main.cpp
#include "a.h"
#include "b.h"
int main() {
foo1();
foo2();
return 0;
}

Related

How can I call to function that exists in other file?

Given 2 files, for examples:
file1.c :
int main(){
f();
return 0;
}
file2.c:
void f(){
return;
}
Why I can't call f from file1.c like that?
Because first you need to tell the compiler (declare) that it exists somewhere:
void f(); //function declaration
int main()
{
f();
return 0;
}
Usually, though, it is better to put such declarations in a separate header file (e.g. file2.h) so that later you could include this file (e.g. #include "file2.h") instead of duplicating such declaration in every other file where you need this function.
The problem is that file1.c does not "know" that the function f exists. You need to use a prototype. The standard way is to put prototypes in header files and definitions in .c files.
It could look like this:
file1.c:
#include "file2.h"
int main(){
f();
return 0;
}
file2.h:
#ifndef FILE2_H
#define FILE2_H
void f();
#endif
file2.c:
#include "file2.h"
void f(){
return;
}

function runs though header is not included

consider the following code, which causes a weird behavior:
foo.h
#ifndef FOO_H
#define FOO_H
void foo();
#endif
foo.c
#include <stdio.h>
// NOTICE - foo.h is not included!
void foo()
{
printf("foo!\n");
}
main.c
#include "foo.h"
int main()
{
foo();
return 0;
}
running this code I get in the console: foo!
what bugs me here is that I expected that main.c would not be familiar with the implementation of foo(), since foo.h is not included in foo.c, and hence foo() should be an inner function in foo.c. It happened to me both when I ran it in VS2010 and when I compiled an exe using gcc (on windows).
can someone explain this phenomenon? I thought about it and I have no idea why it happens. thanks.
The header file is declaring the function, so when compiling main.c the compiler knows the function signature to validate against. When compiling foo.c, it doesn't need to be declared, as it is the declaration of the function. It is up to the linker to see if there are any unresolved symbols, which there aren't in this case, so all is good, and also why you're seeing this work.
What will happen if there was another function(test.c) included in the above question.
foo.h
#ifndef FOO_H
#define FOO_H
void foo();
#endif
foo.c
#include <stdio.h>
// NOTICE - foo.h is not included!
void foo()
{
printf("foo!\n");
}
test.c
#include <stdio.h>
void foo()
{
printf("foo!\n");
}
main.c
#include "foo.h"
int main()
{
foo();
return 0;
}

What happens when including header with static declarations?

For example, let's say I have 2 header files.
a.h
#include <stdio.h>
static __inline foo()
{
// do something
}
Then a.h file gets included into b.h:
b.h
#include "a.h"
void bar();
With corresponding b.cpp file:
b.c
#include "b.h"
void bar()
{
foo();
}
main.c
#include "b.h"
void main()
{
bar();
}
Is foo() going to be inlined in b.c file?
Is foo() (static) going to be visible in main.c file since it's included via b.h file or it will be just visible to b.c? (Would guess that it won't be visible since they are not in same translation unit).
foo() is visible in both b and main. The compiler sees the files after the preprocessor has done its job.
main.c after the preprocessor step:
<all the stuff from stdio.h>
static __inline foo()
{
// do something
}
void bar();
void main()
{
bar();
}
One way to remove foo() from main.c is to move inclusion of a.h from b.h to b.c:
Modified b.h:
void bar();
Modified b.c:
#include "a.h"
#include "b.h"
void bar()
{
foo();
}
Is foo() going to be inlined in b.c file?
It is better to say "inlined" into function bar(). Probably it is, but not guaranteed. It is a compiler's decision to inline function or not. Marking function as inline is often just a hint, that may be ignored. Refer to your compiler docs to clarify actual behavior.
Is foo() (static) going to be visible in main.c file since it's
included via b.h file or it will be just visible to b.c? (Would guess
that it won't be visible since they are not in same translation unit).
foo() is visible in every translation unit that includes a.h directly or indirectly. Assuming inlining was ommited, there is another interesting point: each translation unit defines its own copy of foo() i.e. machine code for foo() will be generated for each compiled source. It may be wasteful for non-trivial functions since it leads to bloating of generated code. As consequence you should define static functions in headers only if they are small and are intended to be inlined.

Unresolved External Symbol with external get function

I keep getting a linker error with the following setup.
I have file1.c which contains the following code
#if defined( _TEST_ENABLED )
int get_value()
{
.
.
.
}
#endif /*_TEST_ENABLED */
I have file2.c which includes file2.h, which defines _TEST_ENABLED. file2.c makes a call to get_value(), however the linker isn't having any part of that.
I've exhausted a lot of different options with zero success. Now i'm asking for help :)
If file1.c does not include file2.h or any file which defines _TEST_ENABLED, _TEST_ENABLED will not be defined when the preprocessor runs on file1.c, so int get_value() { ... } will not get compiled.
In order to call a function in another file:
1) The files must be compiled or at least linked together. The easiest way to do this is gcc file1.c file2.c, however you can also compile both files to *.o files and then link together.
2) The calling file must have, usually through an included header, a prototype of the function. This prototype must appear before the function is used. So, if file2.h defines _TEST_ENABLED, then you must (in file2.c) include file2.h, and then either file2.c or file2.h must include file1.h, which must contain a function prototype (int get_value;)
For example:
file1.c
#include <file1.h>
#include <file2.h>
int main() {
get_value();
}
file1.h
#ifndef _FILE2_H
#define _FILE2_H
#define _TEST_ENABLED
#endif
file2.c
#include <file2.h>
#include <file1.h>
#ifdef _TEST_ENABLED
int get_value() {
return 42;
}
#endif
file2.h
#ifndef _FILE2_H
#define _FILE2_H
int get_value();
#endif
Note that for the purposes of the preprocessor, file1.c and file2.c are processed completely separately. When processing file2.c, it MUST find #define _TEST_ENABLED somewhere, which is why file2.c must include file1.h. Since this is getting a little circular, you should add "#include-guards to each header file, as shown above.
There are some ambiguities in your question, but given the following three files, I can compile and build in ANSI C, but I have to include the .h in both .cs:
file1.c
#include "file2.h"
int main(void)
{
someFunc();
get_value();
return 0;
}
#ifdef _TEST_ENABLED
int get_value(void)
{
return 0;
}
#endif
file2.c
#include "file2.h"
int someFunc(void);
int someFunc(void)
{
get_value();
return 0;
}
file2.h
#define _TEST_ENABLED
int get_value(void);

Header/Include guards don't work?

For some reason, I'm getting multiple declarations of content within my header file even though I'm using header guards. My example code is below:
main.c:
#include "thing.h"
int main(){
printf("%d", increment());
return 0;
}
thing.c:
#include "thing.h"
int increment(){
return something++;
}
thing.h:
#ifndef THING_H_
#define THING_H_
#include <stdio.h>
int something = 0;
int increment();
#endif
When I attempt to compile this, GCC says that I have multiple definitions of the something variable. ifndef should make sure that this doesn't happen, so I'm confused why it is.
The include guards are functioning correctly and are not the source of the problem.
What happens is that every compilation unit that includes thing.h gets its own int something = 0, so the linker complains about multiple definitions.
Here is how you fix this:
thing.c:
#include "thing.h"
int something = 0;
int increment(){
return something++;
}
thing.h:
#ifndef THING_H_
#define THING_H_
#include <stdio.h>
extern int something;
int increment();
#endif
This way, only thing.c will have an instance of something, and main.c will refer to it.
You have one definition in each translation unit (one in main.c, and one in thing.c). The header guards stop the header from being included more than once in a single translation unit.
You need to declare something in the header file, and only define it in thing.c, just like the function:
thing.c:
#include "thing.h"
int something = 0;
int increment(void)
{
return something++;
}
thing.h:
#ifndef THING_H_
#define THING_H_
#include <stdio.h>
extern int something;
int increment(void);
#endif
The header guards will stop the file from being compiled more than once in the same compilation unit (file). You are including it in main.c and thing.c, so it will be compiled once in each, leading to the variable something being declared once in each unit, or twice in total.
try to avoid defining variables globally.
use functions like increment() to modify and read its value instead.
that way you can keep the variable static in the thing.c file, and you know for sure that only functions from that file will modify the value.
The variable something should be defined in a .c file, not
in a header file.
Only structures, macros and type declarations for variables and function prototypes
should be in header files. In your example, you can declare the type of something as extern int something in the header file. But the definition of the variable itself should be in a .c file.
With what you have done, the variable something will be defined
in each .c file that includes thing.h and you get a
"something defined multiple times" error message when GCC tries to link
everything together.
what ifndef is guarding is one .h included in a .c more than once. For instance
thing. h
#ifndef
#define
int something = 0;
#endif
thing2.h
#include "thing.h"
main.c
#include "thing.h"
#include "thing2.h"
int main()
{
printf("%d", something);
return 0;
}
if I leave ifndef out then GCC will complain
In file included from thing2.h:1:0,
from main.c:2:
thing.h:3:5: error: redefinition of ‘something’
thing.h:3:5: note: previous definition of ‘something’ was here

Resources