This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS

struct.h:

#ifndef _STRUCT_H
#define _STRUCT_H

int i;

#endif

main.c:
#include "struct.h"
void main(void)
{
	i = 1;
}

when compiled and linked,error is showed as follow:

Build target 'Target 1'
compiling main.c...
linking...
*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS
SYMBOL: I
MODULE: struct.obj (STRUCT)
Program Size: data=9.0 xdata=4 code=16
Target not created

What is the problem?
Note:no error if compiled in C compiler.

  • "no error if compiled in C compiler."

    Well, of course there isn't: you can only get Linker errors from the Linker!!

    See my reply here:
    http://www.keil.com/forum/docs/thread1812.asp

    Your file struct.h contains a definition of i; presumably you are also #includeing it in another 'C' source file (struct.c?) so that file will also contain a definition of i - presto! multiple definitions!

    You need to define i in one file only (eg, main.c) and then just have an extern declaration in your header file.

    BTW: 'i' is a particularly bad name for a global variable!

  • I think the two statements don't do any work as they do in C compiler in struct.h:

    #ifndef
    #define
    
    Is that right?
    You are right,Andrew Neil,I can use extern.
    BTW:there are only the two files,main.c and struct.h in project

  • "I think the two statements don't do any work as they do in C compiler"

    Pardon?
    I don't understand what you're trying to say!

    Those lines are a standard 'C' coding practice known as an Include Guard - their purpose is to prevent any problems if you (accidentally) #include the same file twice.

  • If the only files in your project are main.c and struct.h, then where did struct.obj come from?
    It certainly looks like two OBJ files are being linked together, and both of them contain a definition for "i".

    The "ifndef" syntax used here is usually used to protect against the case where a header file is included twice, maybe because another header file references it. It does NOT mean you don't have to use "extern".

    It is safest to make all variable declarations in ".h" files use extern, and then only actually declare the variable (without extern) inside one (and only one) ".c" file.

  • There aren't those two lines in any header files in INC directory of KEIL
    why?

  • Originally I am puzzled by the OBJ file.
    Really there are only two files in project,I have no idea where this OBJ file comes from.

    Thanks to safest suggestion

  • "If the only files in your project are main.c and struct.h, then where did struct.obj come from?"

    Maybe he compiled struct.h - if you add a header to a uVision Project, it will get compiled unless you uncheck the 'Include in Target Build' option for the file.

    "It certainly looks like two OBJ files are being linked together, and both of them contain a definition for 'i'."

    Yes, if he did compile struct.h he would end up with a struct.obj containing a definition of i!

    "It is safest to make all variable declarations in '.h' files use extern, and then only actually declare [sic] the variable (without extern) inside one (and only one) '.c' file."

    This is where we need to take great care to distinguish between definitions and declarations:
    A declaration simply informs the Compiler about an identifier; it creates no code and allocates no memory;
    A definition actually provides the code to implement a function, or allocates the storage space for a variable.

    Therefore, in general, declarations should go in headers and definitions in '.c' files - and multiple definitions in the same scope are not allowed.

    (BTW: This is all standard 'C' stuff; nothing specifically to do with Keil.)

  • Dear Mike Hwang,

    I think you need to brush up on your C before continuing on the embedded development path. Your problems stem from a lack of understanding about the C language.

    1. Do *not* put code or define data in an include file. It is extremely bad style and error prone.

    2. Always use include guards in your .h files but *don't* use leading underscores like the implementation header files do. Leading underscores followed by an uppercase letter or another underscore are reserved for use by the implementation.

    3. If you want to share a global variable with another C module then define in it in one C module and extern it in that C module's .h file. Then, simply include that .h file in the other C modules that require knowledge of the global variable. E.g.

    
    /* Foo.c */
    int foo_var;
    
    /* Foo.h */
    #ifndef FOO_H_INCLUDED
    #define FOO_H_INCLUDED
    
    extern int foo_var;
    
    #endif /* FOO_H_INCLUDED */
    
    /* Bar.c */
    #include "foo.h"
    
    int main(void)
    {
        foo_var = 12;
        return 0;
    }

    3. C source files must be compiled in to machine code if you want to run them. This code is typically placed in a relocatable object file, often with a .obj or .o extension. One or more object files are then passed on to the linker/locater which takes them and fixes up their relative addresses with absolute addresses. The linker also pulls object code from the C library at this stage too.

    Hope this helps,

    - Mark

  • uncheck the 'Include in Target Build' option for the file.
    good suggestion

    At the end,thanks to everybody.

  • You can include a header file which declares an identifier in the source file which defines that identifier; eg,

    /* Foo.h */
    #ifndef FOO_H_INCLUDED
    #define FOO_H_INCLUDED
    
    extern int foo_var;
    
    #endif /* FOO_H_INCLUDED */
    
    
    /* Foo.c */
    #include "Foo.h"
    
    int foo_var;
    The advantage to doing this is that the compiler can warn you if the declaration doesn't match the definition