undefined reference to `func()' - c

I'm making some change to an existing linux c project.
In /vobs/ua/HDL/VHDL/CmdUtil/src/help.c, I define func like this:
void func(){
...
}
In file /vobs/ua/HDL/Interface/cli/src/cliSystem.C, I write this code:
extern void func();
...
void func1(){
...
func();
...
}
In file /vobs/ua/HDL/VHDL/DsnMgr/src/shell.c, I write this:
extern void func();
...
void func2(){
...
func();
...
}
In file /vobs/ua/HDL/VHDL/DsnMgr/src/shell.c, I write this:
extern void func();
...
void func2(){
...
func();
...
}
In file /vobs/ua/HDL/VHDL/lib2v/src/asicLibCells.C, I write this:
extern void func();
...
void func3(){
...
func();
...
}
I didn't declare func in any header files.
The problem is, for the call to func in vobs/ua/HDL/Interface/cli/src/cliSystem.C and /vobs/ua/HDL/VHDL/lib2v/src/asicLibCells.C, there is error
undefined reference to `func()'
But for /vobs/ua/HDL/VHDL/DsnMgr/src/shell.c, there is no error.
After I declare func in vobs/ua/HDL/Interface/cli/src/cliSystem.C and /vobs/ua/HDL/VHDL/lib2v/src/asicLibCells.C like this:
extern "C" void func();
There is no error in /vobs/ua/HDL/VHDL/lib2v/src/asicLibCells.C, but the error in vobs/ua/HDL/Interface/cli/src/cliSystem.C persists.
What's wrong? What can I do to eliminate this error?

The problem is that the function func is a C function, and you try to call it from a C++ function. This is problematic because C++ does something called name mangling to allow things like function overload.
That means when you do your declaration
extern void func();
the C++ compiler will mangle the symbol and that mangled symbol will not be found.
In C++ you have to inhibit this name mangling for functions that comes from C object files. This is done with a special extern declaration:
extern "C" void func();
On a slightly related note, in C a declaration like
void func();
doesn't mean that the function takes no arguments like it does in C++. In C that declaration means that func takes an unspecified number of unspecified arguments. In C you must use void to declare a function that takes no arguments:
void func(void);

C++ has a thing called name mangling so that you can overload functions. If you are compiling code as C++, the declaration
extern void func(void);
will add extra characters to its name to encode the fact that it has no parameters. You can disable this by telling the C++ compiler to use C conventions:
extern "C" void func(void);
or
extern "C" {
void func(void);
}
It's normal, however to put these in a header that can be included from both C and C++ files:
#if defined __cplusplus
extern "C" {
#endif
void func(void);
// other function declarations
#if defined __cplusplus
}
#endif

Related

function declaration problem in multi file c project

I have a project that includes three files in codeblocks:
main.c :
#include <stdio.h>
#include <conio.h>
int global = 10;
void f1(int);
void f1_1(int);
void f2(void);
int main()
{
int x = 5;
printf("inside main file");
getch();
f1(x);
f2();
getch();
return 0;
}
file1.c :
#include <stdio.h>
#include <conio.h>
void f1(int x)
{
printf("\ninside file1 >> f1 and x = %i", x);
getch();
f1_1(x);
}
void f1_1(int x)
{
printf("\ninside file1 >> f1 >> f1_1 and x = %i", x);
getch();
}
file2.c :
#include <stdio.h>
#include <conio.h>
extern int global;
void f2()
{
printf("\ninside file2 >> f2 function , global var = %i", global);
getch();
}
When I compiled it, I got these warnings:
c|8|warning: implicit declaration of function 'f1_1'; did you mean 'f1'? [-Wimplicit-function-declaration]
c|11|warning: conflicting types for 'f1_1'
What should I do for this?
void f1(int);
void f1_1(int);
void f2(void);
Should be:
extern void f1(int);
extern void f1_1(int);
extern void f2(void);
Or, as #kiranBiradar points out, you can declare them in header files
file1.h
#pragma once
extern void f1(int);
extern void f1_1(int);
file2.h
#pragma once
extern void f2(void);
Note the use of the extern keyword. When you forward declare a function in a file as void f(void), the symbol 'f' is public, meaning other compilation units can reference it. When you declare it as extern void f(void), then the compiler doesn't expect the function to be defined in that compilation unit and leaves it up to the linker to find that symbol.
This is the perfect time to learn about the important concept of translation units.
Each single source file, with all included header file, forms a single translation unit. Each translation unit is separate and distinct and compiled stand-alone without any knowledge of other translation units.
That means symbols declared in e.g. the main.c source file will not be known in the file1.c source file.
When you compile file1.c the compiler simply doesn't know about the f1_1 function declaration you have in the main.c source file, so you get a warning about that fact.
To solve your problem, you need to declare the f1_1 function in the file1.c file. Either by adding a forward declaration (like the one you have in main.c), or moving the whole function definition (implementation) of f1_1 above the f1 function.
Or you could create a single header file which contains all the declarations needed (for the f1, f1_1, f2 function, plus the global external variable declaration), and include this single header file in all your source files. This solution works best if you have multiple symbols (functions, variables, etc.) that are used in multiple translation units.
My personal recommendation is this: Since the f1_1 function is only used internally inside the file1.c source file, move its definition above f1, and make it static. Then remove its declaration from the main.c source file.
Regarding the "implicit declaration" and "conflicting types" warnings, it's because in older standards of C it was allowed to not declare functions and the compiler would create an implicit declaration by guessing the declaration based on the first call of the function.
The important part about the guessing is that only the arguments were guessed, the return type would always be int.
I don't know the exact wording in the specifications about this since it was removed in the C99 specification, but most compilers still allow this with only emitting a warning instead of an error. This is where the first warning comes from.
However, the return type of int is still being used. And since your f1_1 function is declared to return void later in the file1.c source file, there's a mismatch between the guessed declaration (int f1_1(int)) and the actual declaration (void f1_1(int)) which leads to the second warning.

Two versions of same function: inline and normal?

I'd like to inline some functions, however, they are shared across the team and I don't want to force people to use them.
What would be the best way to add inline versions?
// normal
int func1();
int func2();
// inline versions
inline int inl_func1() { ... }
inline int inl_func2() { ... }
Would something like that make sense?
Edit:
Ideally:
I wouldn't have to write the same function definitions (function body) twice.
It would all be handled with s single define.
Declare/define the inline version and declare the non-inline version in the header file with different names.
// "func.h"
// normal
int func1(void);
int func2(void);
// inline versions
static inline int func1_inline(void) { ... }
static inline int func2_inline(void) { ... }
This allows a user to use either form or both. There is little compelling reason to use the same name and only allow one form.
Both can be handy for code that needs speed vs. space on some calls and not others.
This has a benefit that the one .c file that defines/implements func1(), func2() can use simple code to insure equivalent functionality.
#include "func.h"
int func1(void) {
return func1_inline();
}
int func2(void) {
return func2_inline();
}
BTW, declaring a function like int func1(); does not mean the same as int func1(void);. int func1(); means func1 returns an int, but provids no information about what can be passed to it. It is more like pseudo-code int func1(...);
Perhaps you could tell the people who want the inline functions to define a specific macro before including your header file:
#define WANT_INLINE_FUNC1
#include "awesome_funcs.h"
People who want the to call the externally linked function should omit the macro:
#include "awesome_funcs.h"
Then, in "awesome_funcs.h":
#ifdef WANT_INLINE_FUNC1
inline int func1(int param)
{
/* function body here */
}
#else
extern int func1(int param);
#endif
You also need to define a copy of the function with external linkage in one of your library files, e.g. in "awesome_funcs.c":
#define WANT_INLINE_FUNC1
#include "awesome_funcs.h"
/*
* This will define func1 with external linkage,
* but the function body is copied from the inline definition
* in "awesome_funcs.h".
*/
extern int func1(int param);
EDIT 1
You could combine this with chux's answer and get the best of both worlds (unless that makes things too confusing for your users). Just replace func1 in "awesome_funcs.h" with the following:
static inline int inl_func1(int param)
{
/* function body here */
}
#ifdef WANT_INLINE_FUNC1
inline int func1(int param)
{
return inl_func1(param);
}
#else
extern int func1(int param);
#endif
Then inl_func1 will always be the inline version, and func1 may or may not be inline, depending on whether or not the WANT_INLINE_FUNC1 macro was defined before including "awesome_funcs.h".
What would be the best way to add inline versions?
Your easiest course of action would be to declare static inline versions of these functions:
static inline int func1() { ... }
static inline int func3() { ... }
The function names do not need to differ from those of the corresponding external functions. However, if you #include a header that has declarations of functions with those names, then they must be compatible, AND there must be prior static declarations. For example:
static inline int func1(/* params */);
static inline int func3(/* params */);
#include "our_functions.h"
// ...
static inline int func1(/* params */) {
// implementation ...
}
static inline int func3(/* params */) {
// implementation ...
}
This will allow you to add inline versions without modifying your existing code that calls the external versions of these functions, and without affecting any other translation units. There is at least one alternative, but I don't see anything to recommend it over the above for your particular circumstances.

Splitting main file into modules in C

I have three files as such:
module.c:
void bar() {
foo();
}
module.h: (i didn't put the include guard for simplicity)
void bar();
main.c
void foo() {
//some code
}
int main() {
bar();
}
when compiling main.c and module.c, module.c returns an error saying foo() is not defined. How can i fix this up?
Basically, i wanted to take my actual main file, which was pretty large, and split up parts of it to other files for readability, but those functions call other functions found in main
It's tricky because of the directions your dependencies are going.
I can split your code into three compilation units: main.c, module.c, and foo.c
If you do this, you don't have any foo code in main, main only calls bar, and bar includes foo, which is defined in foo.
main.c
#include "module.h"
int main() {
bar();
}
module.c
#include "foo.h"
void bar() {
foo();
}
foo.c
void foo() {
}
Best of all is that you don't need to declare foo outside of foo.h, or bar outside of module.h.
I guess module.h could also define void foo(); thus module.c would implement foo too. On the other hand, if bar depends indirectly on foo, then maybe module.c should include another_module.h implemented by another_module.c.
Put prototype definitions for all your functions into module.h:
int main(int argc,char **argv);
void foo(void);
void bar(void);
int fludger(int abc,char *str);
You get the side benefit that in addition to putting any function in any .c file you wish, you no longer need to order the functions within a given .c file, based upon what calls what [e.g. before if foo called bar, bar would have to be defined above foo]

Declare function as non-static and implement as static inline

I want to write different implementations for my function, some inline and some not. Thus, I want to declare the function as:
// MyHeader.h
int myFunc(void);
#if DO_INLINE
static inline int myFunc(void) { return 42; }
#endif
And then also have:
// MySource.c
#if !DO_INLINE
#include "myHeader.h"
int myFunc(void) { return 42; }
#endif
I'll specify DO_INLINE at compile time.
MSVC has no problems with this, but GCC (4.1.1) complains that I'm declaring a static function after I've already declared it as non-static. If I remove the static qualifier, and #include "MyHeader.h" from more than one compilation unit, it will complain about multiple definitions. (As if the inline functions are extern.) I don't quite understand why the compiler has problems with this.
I think this should be pretty obvious and unambiguous:
int myFunc(void);
static inline int myFunc(void) { return 42; }
It shouldn't require the declaration to be static.
That said, there is a solution to my problem that I'm trying very hard to avoid:
#if DO_INLINE
#define MAYBE_STATIC static
#else
#define MAYBE_STATIC
#endif
MAYBE_STATIC int myFunc(void);
EDIT: Here is a more realistic use case for this: http://codepad.org/OkC0Su3v
This header.h should work:
// MyHeader.h
#if DO_INLINE
static inline int myFunc(void) { return 42; }
#else
int myFunc(void);
#endif
Figured it out closely enough. The implementation should be defined as "extern inline" instead:
// MyHeader.h
int myFunc(void);
#if DO_INLINE
extern inline int myFunc(void) { return 42; }
#endif
The compiler will inline this function where it sees fit, but still compile it once as a function, to make it available for linking. That part I don't need, but it doesn't really hurt.

Linker error inline function

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;
}

Resources