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

MULTIPLE PUBLIC DEFINITIONS ?

i write a global.h file:

#ifndef GLOBAL_H
#define GLOBAL_H

int nGlobal;
#endif

//file A.c
#include "global.h"
....

//file B.c
#include "global.h"
....

Build target 'Target 1'
compiling A.c...
compiling B.c...
linking...
*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS
SYMBOL: nGLOBAL
MODULE: A.obj
*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS
SYMBOL: nGLOBAL
MODULE: B.obj

oh,why the error do not happen when i write code "#include <reg51.h>" in several .c files.
please help me,thank you very much.

Parents Reply Children
  • "int a" tells the compiler to reserve space for an integer. If you put such a statement in a header file, and #include it in several places, you are telling the compiler to reserve space for several integers, each of which has the same name -- which upsets the linker. Hence, you use

    extern int a;

    which does not reserve any space, but merely makes a name public. The space will typically be reserved by another statement in some single .c file which defines an integer named "a".

    "sfr" and "sbit" do not reserve space. They merely identify bits that already exist in the registers of the processor, which cannot be created or destroyed by the linker. The statements are declarations rather than definitions, and thus can be safely included in headers. I agree it perhaps would be more consistent if it were "extern sfr" and "extern sbit". But then, no doubt some programmers would be left searching for the actual definition to go with the declaration.

  • "2, C51 is not a C++ compiler, it's true. In the [C++] book, there are namespaces and classes which can be put in headers. But I delete them."

    That's all good and fine for an experienced programmer who clearly understands these things - but recommending a C++ book to a novice who is obviously having some problems with basic ANSI 'C' concepts is, I suggest, somewhat unhelpful?

  • "int a" tells the compiler to reserve space for an integer.

    Close, yet not quite completely correct. The statements

    int a = 0;
    int b = some_value;
    do indeed and unquestionably reserve space for an integer (and initialize it), right then and there. But the case of
    int a;
    without an initializer is trickier.

    This is what the standard calls a tentative definition. That's to say it is interpreted as just a declaration, i.e. as if you had written
    extern int a;
    until the compiler has finished with the source file in question. If, and only if there was no initialized definition of the object found until then, the tentative definition is turned into a real definition, and will actually reserve space. That's how it comes that
    int a;
    int a;
    int a = 5;
    is allowed, while
    int a = 5;
    int a = 5;
    isn't.

    And to make matters worse, the C language definition leaves it open to the implementor to decide what happens if two separate compilation units (vulgo: source files) both contain only tentative definitions of a same-named object. Most Unix-born C toolchains out there will happily accept a program that has
    int a;
    in a header #include'd by several source files --- they'll just join all these tentative definitions into a single object, thus extending the tentative status of the definition beyond the source file's compile time, until the time the whole program is linked.