Multiple definition and header-only libraries

夙愿已清 提交于 2019-11-29 03:36:11

If you define your variables inside your header file and include the header in several c files, you are bound to get multiple definitions error because you break the One definition rule(ODR), which states that there should be only one definition in one Translation Unit(header files + source file).

Solution is:
You should define the entities you get Multiple definition errors for only once.
For Functions:
Declare the function prototypes in header file(which you include in other source files) and define the function in one and only one source file.
For Global variables:
You declare the variable extern in header file(which you include in other source files) and then define the variable in one and only one source file.

Ahmed Masud

You are missing the point of #ifndef _FOO_H / #define _FOO_H / #endif construct. That only protects against multiple inclusions in ONE file. For example they protect against this:

foo.h:

  #ifndef _FOO_H 
  #define _FOO_H

  /* some C stuff here */

  #endif /* _FOO_H */

foo.c:

   #include <foo.h>
   #include <bar.h>
   ...

bar.h:

   #include <foo.h>
   ...

note that foo.c and bar.h both include foo.h; here the #ifdef _FOO_H / #define _FOO_H / #endif protects against that double inclusion in foo.c ( the foo.h included in bar.h doesn't redefine stuff )

Now the next part.

Why would you move function implementation from utils.c to utils.h? Also why did you decide to make it "header-only" ?

You can, depending on whether your compiler supports static inline functions do this; but even then it's NOT recommended, as more than likely, it will make your program unnecessarily bloated because chances are your util functions are quite complex and cannot be inlined anyways.

So change it back to utils.c and utils.h construct that you had before which, i presume, WAS working and enjoy the software.

You're violating the One-Definition-Rule. Each function must be defined precisely once, while you end up defining it in each translation unit.

You simply cannot do something like this:

// header.h
void foo() { }

// file1.c
#include "header.h"

// file2.c
#include "header.h"

The only real solution is to declare void foo(); in the header and define it once only (usually in a dedicated foo.c). The same goes for global variables, which should be declared as extern in the header and defined in the source file.

Include guards have nothing to do with this. They only serve to prevent recursive self-inclusion or redundant multiple inclusion within one translation unit.

If you indend for the utils.h functions to be "copied" into each place where it is used, just use static functions in the header. (static inline in C99)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!