This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Problem with multiple declarations in C

Genius 4170 points


HEllo everyone,

i did not find the forum for C programming, so i will post in here, because i try to use this code on my MSP430 processor, I hope this will also result in some answers :)

I have started using multiple *.c-files and therefore multiple *.h-files in my project. I have about 20 different files and everthing seemed to work just fine, now I did want to introduce a new global variable to all my files.

This variabel i placed in my say global.h file, in which all my global variables should one day lie.

[global.h]

 unsigned int uint16_globaltest;

now in my other files i include this global-header:

[main.c] - [func.c] - [foo.c]...... as often as i want

#include "global.h"

extern unsigned uint16_globaltest;

Now i will get CCS error messages like: symbol "uint16_globaltest" redefined: first defined in "func.obj"; redefined in "./main.obj"

I did find out some soultions in the web like introduce some structure like:

[global.h]

#ifndef EXTERN

#define EXTERN extern

#endif  

EXTERN unsigned uint16_globaltest;

And I suppode i will implement that and it should work, but here is my question:

In every header file the normal structure is:

#ifndef GLOBAL_H_
#define GLOBAL_H_

unsigned int uint16_globaltest;

#endif

Shouldnt this code already implement that the header file is ONLY declared ONCE and not more????

For me right now it seems, that the header is included in every single c-file, because I get the error messages with multiple variabel defines.

Could somebody tell me am I thinking wrong, or is something wrong with my compiler settings?

Thanks a lot,

Best wishes,

Seb

  • seb said:
    i did not find the forum for C programming

    Take a look here: http://c-faq.com/

    I also give a number of other links to general 'C' resources here: http://blog.antronics.co.uk/2011/08/08/

    This variabel i placed in my say global.h file, in which all my global variables should one day lie.

    It might get more appropriate to group your variables by some meaningful association - rather than just dump everything arbitrarily into 1 big header...

    http://en.wikipedia.org/wiki/Cohesion_(computer_science)

    http://www.kodefuguru.com/post/2009/10/05/Coincidental-Cohesion.aspx

    [global.h]

     unsigned int uint16_globaltest;

    That is a definition of uint16_globaltest

    now in my other files i include this global-header:

     So, obviously, each of those files will contain the  definition of uint16_globaltest - and CCS is correct to tell you that the symbol is being re-defined in each one!

    This is what you should do:

    #include "global.h"

    extern unsigned uint16_globaltest;

    because that is just a declaration of uint16_globaltest.

    It is important that you understand the difference between a  definition  and a declaration

    See: http://c-faq.com/decl/decldef.html

    This should be covered in any decent 'C' textbook - see links above.

    I did find out some soultions in the web like introduce some structure like:

    [global.h]

    #ifndef EXTERN

    #define EXTERN extern

    #endif  

    EXTERN unsigned uint16_globaltest;

    Yes, some people like to do that - but I'm with the 'C' FAQ on this:

    The 'C' FAQ said:
    It is possible to use preprocessor tricks ... but it's not clear if this is worth the trouble

     

     

    seb said:
      but here is my question:

    In every header file the normal structure is:

    #ifndef GLOBAL_H_
    #define GLOBAL_H_

    unsigned int uint16_globaltest;

    #endif

    Shouldnt this code already implement that the header file is ONLY declared ONCE and not more????

    The above is to prevent against the same header file being included multiple times into a single file - it has nothing to do with the issue of multiple 'C' language symbol definitions over the entire project!

     

  • Andy Neil said:

    This is what you should do:

    #include "global.h"

    extern unsigned uint16_globaltest;

    [/quote]

    Sorry - that's wrong!

    What you should do is to have this in your header file:

    global.h said:
    extern unsigned uint16_globaltest;

    And then your .c files just include the header:

    *.c said:
    #include "global.h"

    But one of your .c files - no more; no less - must contain the definition; eg,

    global.c said:
    #include "global.h"  // Contains the declaration 

    unsigned uint16_globaltest;   // This is the definition

    Note that including the header here is OK and has the distinct advantage that the compiler will be able to spot any discrepancies between the declaration (in the header) and the definition. (This is the key reason why I don't go for the preprocessor tricks)

  • Thanks a lot Andy, this really put some things together for me.

    I will write down the essential part of external usage in header files, for those who didnt know:


    When you need to share variables or functions across several source files, you will of course want to ensure that all definitions and declarations are consistent. The best arrangement is to place each definition in some relevant .c file. Then, put an external declaration in a header (``.h'') file, and #include it wherever the declaration is needed. The .c file containing the definition should also #include the same header file, so the compiler can check that the definition matches the declarations.


    From my post till now, I did do the workaround with the macros defining an EXTERN to extern, but i will rewrite everything, since it is not that much. But it did work, just for your information.

  • Andy Neil said:
    your .c files just include the header:

    #include "global.h"

    But one of your .c files - no more; no less - must contain the definition; eg,[/quote]

    To be completely general, the definition does not necessarily have to be in a .c file - it could be in a Library file, or a source file in another language.

    The important thing is that the definition must exist exactly once somewhere in the project.

    Many people miss this point when using Libraries:  they #include the header(s) with the extern declarations, but don't also include the Library (whether in source or "binary" form) with the definitions!

    This results in "Undefined Symbol" or "Unresolved External" or similar messages from the Linker.

    eg, see: http://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/471/t/165008.aspx

  • Andy Neil said:
    The important thing is that the definition must exist exactly once somewhere in the project.

    Some compiler/linker combos accept a definition in more than one compilation unit, if at most one (but even none) contains an initialization.
    However, such an incomplete definition may appear only once in a compilation unit.

    If a global variable is not initialized (has no "= x" part), then no 'extern' is needed even in the header file and no explicit definition is needed in any .c file.

    The trick is that an 'extern' declaration does not put any symbol reference into the object file. The name is jsut used in teh code (and therefore linked later) but the compiler does not generate an entry for the variable itself (jsut the same as for external functions).

    If an incomplete definition (no initialization) is used, the compiler will put an information about a global object with this name and size, but will not put a statement to actually create it. The linker will then be able to identify multiple of those infos as referrign to the same, and if no complete declaration is found anwhere, it will silently add one and put this variable into the noninitialized data section.

    However, this depends on the compiler/linker combo and the use of 'extern' in the header file and a complete definition in the .c file that belongs to the header file is the clean (and conforming) way.

**Attention** This is a public forum