开发者

defining a function twice in 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.

d开发者_JAVA百科oes 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜