3

I have the following code layout

header.h

#ifndef _header_h
#define _header_h
void empty(float *array, int l)
{
    int i;
    for (i=1 ; i<=l ; i++)
    {
        array[i]=0;
    }

}

#endif

and two files (lets call them file1.c and file2.c)

#include "header.h"

void function/*1 or 2*/(){

     ....
     empty(a,b);
     ....
}

So compiling works fine but the linker command fails as the compiler says that there is a duplicate function definition. How can I avoid that with still using the header file? It is working fine when I only define the function in the header and create another .c file containing the full function. I always thought declaring it in the header is the way to go.

Sam
  • 7,252
  • 16
  • 46
  • 65
MaxJ
  • 157
  • 1
  • 7

3 Answers3

4

I always thought declaring it in the header is the way to go.

Yes, it is. Declaring it in the header is fine. It is not any good to define it in a header, though. (unless it's static inline, but you probably don't want to do that these days.)

3

You should never have things in a header that require memory in the running program. This is a rough way of specifying it, but it works pretty well in practice.

In other words, the header should only have the prototype for the function, which is a compile-time thing that doesn't "exist" in the running program (unlike the code of the function itself, which of course exists at runtime):

void empty(float *array, int l);

Then put the code in a separate C file, which you compile and link separately.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • "You should never define things in a header". Except when *things* are enums or typedefs. – Nikolai Ruhe Jun 10 '14 at 15:23
  • @NikolaiRuhe No, those are *declarations*. A definition is (typically) something that takes memory in the compiled program. Like the code of a function or the bits of some variable ("object"). – unwind Jun 10 '14 at 15:31
  • The C11 Standard claims otherwise. See 6.7 (5) Declarations: "A definition [... for an enumeration constant] is the (only) declaration of the identifier" [and similar for typedef name]. – Nikolai Ruhe Jun 10 '14 at 15:37
  • Also, a `typedef` even has "definition" in its name. – Nikolai Ruhe Jun 10 '14 at 15:40
  • What about "You should never have things in a header that make the compiler emit exported symbols into the object file"? – Nikolai Ruhe Jun 10 '14 at 15:42
  • @NikolaiRuhe Feel free to post your own answer, of course. – unwind Jun 10 '14 at 15:44
1

You have the function empty defined as a global symbol in the header. This means it will be a visible symbol in all compilation units that include it. There are three general workarounds:

  1. make it a static function

    static void empty(...) {...}
    
  2. put the implementation into a separate compilation unit

    in header.h:

    void empty(float *array, int l);
    

    in empty.c implement it

  3. instruct your linker to ignore duplicate symbols. This differs from linker to linker, consult man ld.

    On OS X: -m flag.

    On Linux: -z muldefs

Sergey L.
  • 21,822
  • 5
  • 49
  • 75