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

#ifndef does not work properly

Hello!

I want to include the same headerfile in more than one sourcefile and of course have to take care that each Headerfile is included just once.

I really have no clue, why this works for the Headers provided by Keil but not with my own ones:

#ifndef _MYHEADER_H_
#define _MYHEADER_H_

//Headerfile content
. ..

#endif

Obviously the preprocessor includes the Headerfile more than once and so i get errors.

When i add a statement within my Header like:

#warning "included more than once"

the warning message appears twice. (so the header is really included twice).

Can anyone tell me the problem please?!

Kind regards

Parents
  • The

    #ifndef xx
    #define xx
    ...
    #endif
    

    method is to make sure that a header file isn't included more than once from the same c file.

    You can not - and normally don't want to - stop multiple c files from including the same header file.

    A header file is included because:
    1) You have specifically added a line #include "xx" or #include <xx> in the source file. Don't do that unless you want the file to be included :)
    2) You are including one header file, that it it's turn (one or more steps away) includes another header file. But a header file should only contain a recursive #include if it really needs that other file for some declarations. Hence, you need to include it.

    What does this mean?

    If the header file must be seen by multiple source files, you can't use it to allocate global variables, since the linker would then complain about multiple sets of global variables with the same name. This can be solved with the following:

    //globals.h
    #ifndef _GLOBALS_H
    #define _GLOBALS_H
    
    #if defined MAIN
    #define EXTERN
    #else
    #define EXTERN extern
    #endif
    
    ...
    
    EXTERN int my_global_variable;
    
    #endif // _GLOBALS_H
    

    // main.c
    #define MAIN
    #include "globals.h"
    ...
    // misc.c
    #include "globals.h"
    ...
    

    In this case, only the inclusion in main.c will result in an "allocation" of global variables, because the #define EXTERN will be empty. All other source files that includes "globals.h" will just see the type information for the global variables.

Reply
  • The

    #ifndef xx
    #define xx
    ...
    #endif
    

    method is to make sure that a header file isn't included more than once from the same c file.

    You can not - and normally don't want to - stop multiple c files from including the same header file.

    A header file is included because:
    1) You have specifically added a line #include "xx" or #include <xx> in the source file. Don't do that unless you want the file to be included :)
    2) You are including one header file, that it it's turn (one or more steps away) includes another header file. But a header file should only contain a recursive #include if it really needs that other file for some declarations. Hence, you need to include it.

    What does this mean?

    If the header file must be seen by multiple source files, you can't use it to allocate global variables, since the linker would then complain about multiple sets of global variables with the same name. This can be solved with the following:

    //globals.h
    #ifndef _GLOBALS_H
    #define _GLOBALS_H
    
    #if defined MAIN
    #define EXTERN
    #else
    #define EXTERN extern
    #endif
    
    ...
    
    EXTERN int my_global_variable;
    
    #endif // _GLOBALS_H
    

    // main.c
    #define MAIN
    #include "globals.h"
    ...
    // misc.c
    #include "globals.h"
    ...
    

    In this case, only the inclusion in main.c will result in an "allocation" of global variables, because the #define EXTERN will be empty. All other source files that includes "globals.h" will just see the type information for the global variables.

Children
  • Ok!

    Thank you all for the help!

    I am a beginner and NOW i think i understand the purpose of the #ifndef .. :-)

    So in my context i generally would not need it.

    However, i have compiled a Library in Keil and for this Library a Header File exists, in which all Prototypes of the functions defined in the Library are listed.

    If i now include the Header File of this Lib in more than one .c File, get errors which tells me "Multiple public definitions".

    So it seems that the symbols in this Library-Header are "included" more than once?!

    Kind regards!

  • Sorry, the post of Per Westermark should explain this problem. ;-)

    Have overseen it...

    Thanks!!

  • So in my context i generally would not need it.

    It's a good idea to use it in all your header files. Just to be safe.

    However, i have compiled a Library in Keil and for this Library a Header File exists, in which all Prototypes of the functions defined in the Library are listed.

    Maybe you could post a bit of code so all of us can have a look. Make sure you use the ANSI C keyword extern in the header file to tell the compiler that it's a declaration of a variable or function and not a (obviously multiple) definition

    --
    Joost

  • So in my context i generally would not need it.

    Coming from somebody who only just understood what they were ever needed for in the first place, that's a dangerously confident generalization. For the time being, you should follow time-proven coding rules, and one of those is to treat multiple-inclusion guards like your safety belt: don't think about it, just fasten it.

    If i now include the Header File of this Lib in more than one .c File, get errors which tells me "Multiple public definitions".

    That's got nothing to do with multiple-inclusion guards. It's telling you that you have put stuff in your library's public header that doesn't belong in header files: definitions of variables. In short, some variable declarations in your header are missing the "extern" specifier.

  • Try a search for those two keywords together - it's been explained before.

    See also: c-faq.com/.../decldef.html