newbie question about preprocessing

Discussion in 'C Programming' started by sieg1974, Sep 25, 2003.

  1. sieg1974

    sieg1974 Guest

    Hi,

    I have made a program that is divided in many group of functions, and
    each of these groups has its .h and .c files ( for example dutils.h
    and dutils.c ). And to avoid the same .h file to be include more than
    once, I wrote these command everywhere where I need to include
    something.

    #ifndef H_DUTILS
    # define H_DUTILS
    # include "dutils.h"
    #endif

    Is it a good way to do it, or there is a better way?

    Thanks,

    Andre
     
    sieg1974, Sep 25, 2003
    #1
    1. Advertising

  2. sieg1974

    Tom Zych Guest

    sieg1974 wrote:

    > I have made a program that is divided in many group of functions, and
    > each of these groups has its .h and .c files ( for example dutils.h
    > and dutils.c ). And to avoid the same .h file to be include more than
    > once, I wrote these command everywhere where I need to include
    > something.


    > #ifndef H_DUTILS
    > # define H_DUTILS
    > # include "dutils.h"
    > #endif


    > Is it a good way to do it, or there is a better way?


    A better way is to put the same kind of logic inside the header file
    itself:

    #ifndef DUTILS_H /* note changed macro name */
    #define DUTILS_H
    [the rest of the header file here]
    #endif

    Then you only need #include "dutils.h" in the other files.

    --
    Tom Zych
    This is a fake email address to thwart spammers.
    Real address: echo '' | rot13
     
    Tom Zych, Sep 25, 2003
    #2
    1. Advertising

  3. "Tom Zych" <> schrieb im Newsbeitrag
    news:...
    > sieg1974 wrote:
    >
    > > I have made a program that is divided in many group of functions, and
    > > each of these groups has its .h and .c files ( for example dutils.h
    > > and dutils.c ). And to avoid the same .h file to be include more than
    > > once, I wrote these command everywhere where I need to include
    > > something.

    >
    > > #ifndef H_DUTILS
    > > # define H_DUTILS
    > > # include "dutils.h"
    > > #endif

    >
    > > Is it a good way to do it, or there is a better way?

    >
    > A better way is to put the same kind of logic inside the header file
    > itself:
    >
    > #ifndef DUTILS_H /* note changed macro name */


    Why did you change it?
    AFAIK macro-names starting with upper case 'E' are reserved, so prefixing
    the macro-name with H_ puts you on the safe side.

    > #define DUTILS_H
    > [the rest of the header file here]
    > #endif
    >
    > Then you only need #include "dutils.h" in the other files.


    Robert
     
    Robert Stankowic, Sep 25, 2003
    #3
  4. On Wed, 24 Sep 2003, sieg1974 wrote:

    > Hi,
    >
    > I have made a program that is divided in many group of functions, and
    > each of these groups has its .h and .c files ( for example dutils.h
    > and dutils.c ). And to avoid the same .h file to be include more than
    > once, I wrote these command everywhere where I need to include
    > something.
    >
    > #ifndef H_DUTILS
    > # define H_DUTILS
    > # include "dutils.h"
    > #endif
    >
    > Is it a good way to do it, or there is a better way?


    This will work in some instances. It depends a little on your compiler.
    There is nothing in the C standard that indicates this has to work.

    Here is a scenario where this fails. I have a make file. Rather than
    having a single command to compile everything at once I want to compile
    each source file to an object file and then link them all together. In
    case your are curious why, if I have 10,000 source files I don't want to
    recompile all of them if I make a change to just one file.

    If I have two files that #include the same header file, the make command
    will compile the frst file, the compiler will see that this is the first
    time we have included the header and #include it. When I compile the
    second file, this is a new run of the compiler so the compiler will thikn
    we are accessing the header file for the first time, again. When we link
    the object files from file one and file two there will be trouble.

    Bottom line, this might work for you but it depends on how your compiler
    works. Something to note: what would happen if it works for your current
    compiler but two years from now you realize you need to change your setup
    and it stops working? That is, you switch to a system I just described.

    --
    darrell at cs dot toronto dot edu
    or
    main(){int j=1234;char t[]=":mad:abcdefghijklmnopqrstuvwxyz.\n",*i=
    "iqgbgxmdbjlgdv.lksrqek.n";char *strchr(const char *,int);while(
    *i){j+=strchr(t,*i++)-t;j%=sizeof t-1;putchar(t[j]);} return 0;}
     
    Darrell Grainger, Sep 25, 2003
    #4
  5. sieg1974

    sieg1974 Guest

    Tom Zych <> wrote in message news:<>...
    > sieg1974 wrote:
    >
    > > I have made a program that is divided in many group of functions, and
    > > each of these groups has its .h and .c files ( for example dutils.h
    > > and dutils.c ). And to avoid the same .h file to be include more than
    > > once, I wrote these command everywhere where I need to include
    > > something.

    >
    > > #ifndef H_DUTILS
    > > # define H_DUTILS
    > > # include "dutils.h"
    > > #endif

    >
    > > Is it a good way to do it, or there is a better way?

    >
    > A better way is to put the same kind of logic inside the header file
    > itself:
    >
    > #ifndef DUTILS_H /* note changed macro name */
    > #define DUTILS_H
    > [the rest of the header file here]
    > #endif
    >
    > Then you only need #include "dutils.h" in the other files.


    But what would happen if I had two or more .c files that would include
    stdio.h for example? Does stdio.h have these ifndef, define, endif
    inside it? Or will it just be included more than once?

    Andre
     
    sieg1974, Sep 25, 2003
    #5
  6. sieg1974

    Mike Wahler Guest

    "sieg1974" <> wrote in message
    news:...
    > Tom Zych <> wrote in message

    news:<>...
    > > sieg1974 wrote:
    > >
    > > > I have made a program that is divided in many group of functions, and
    > > > each of these groups has its .h and .c files ( for example dutils.h
    > > > and dutils.c ). And to avoid the same .h file to be include more than
    > > > once, I wrote these command everywhere where I need to include
    > > > something.

    > >
    > > > #ifndef H_DUTILS
    > > > # define H_DUTILS
    > > > # include "dutils.h"
    > > > #endif

    > >
    > > > Is it a good way to do it, or there is a better way?

    > >
    > > A better way is to put the same kind of logic inside the header file
    > > itself:
    > >
    > > #ifndef DUTILS_H /* note changed macro name */
    > > #define DUTILS_H
    > > [the rest of the header file here]
    > > #endif
    > >
    > > Then you only need #include "dutils.h" in the other files.

    >
    > But what would happen if I had two or more .c files that would include
    > stdio.h for example?


    Then the text from the stdio header will be pasted into
    each .c file. Note that this will create two separate
    translation units. The header is not being #included
    more than once.

    What I think you might have meant to ask is what
    happens if #include <stdio.h> appears more than
    once in the same source file.

    Answer:
    If the implementation is compliant The Right Thing(tm)
    will happen.

    >Does stdio.h have these ifndef, define, endif
    > inside it?


    It might.

    > Or will it just be included more than once?


    The standard only stipulates that #including
    a standard header more than once has the
    same effect as if #included only once (with
    one exception, see below). How this is achieved
    is up to the implementation, but using 'include
    guards' is common.

    C&V:
    =============================================================
    ISO/IEC 9899:1999 (E)

    [...]

    7.1.2 Standard headers

    [...]

    4 Standard headers may be included in any order; each may be
    included more than once in a given scope, with no effect
    different from being included only once, except that the
    effect of including <assert.h> depends on the definition
    of NDEBUG (see 7.2). If used, a header shall be included
    outside of any external declaration or definition, and it
    shall first be included before the first reference to any
    of the functions or objects it declares, or to any of the
    types or macros it defines. However, if an identifier is
    declared or defined in more than one header, the second and
    subsequent associated headers may be included after the
    initial reference to the identifier. The program shall not
    have any macros with names lexically identical to keywords
    currently defined prior to the inclusion.
    =============================================================

    -Mike
     
    Mike Wahler, Sep 25, 2003
    #6
  7. On Thu, 25 Sep 2003, Darrell Grainger wrote:
    >
    > On Wed, 24 Sep 2003, sieg1974 wrote:
    > >
    > > I have made a program that is divided in many group of functions, and
    > > each of these groups has its .h and .c files ( for example dutils.h
    > > and dutils.c ). And to avoid the same .h file to be include more than
    > > once, I wrote these command everywhere where I need to include
    > > something.
    > >
    > > #ifndef H_DUTILS
    > > # define H_DUTILS
    > > # include "dutils.h"
    > > #endif
    > >
    > > Is it a good way to do it, or there is a better way?

    >
    > This will work in some instances. It depends a little on your compiler.
    > There is nothing in the C standard that indicates this has to work.


    While technically true, that is a vacuous statement. The *only*
    implementation-dependent part of the above is the bit between the
    quotes -- some file systems might not know what "dutils.h" is meant
    to represent. In the context of c.l.c and hosted implementations,
    I think we can assume the OP's compiler has a decent file system.

    The above code does the following:

    Check whether H_DUTILS is defined. This check will be false
    initially, since the implementation is not allowed to define
    H_DUTILS for itself.
    If not, define H_DUTILS,
    and then #include a certain header file.
    Otherwise, do nothing.

    This is perfectly well-defined (except for the bit in quotes, as
    I mentioned), and will work on every C compiler in existence (as
    well as every C compiler *not* in existence).

    [Tangential: Someone else suggested #defining DUTILS_H instead.
    That's harmless in this case, but stupid in general. Don't listen
    to that person.]


    > Here is a scenario where this fails. I have a make file. Rather than
    > having a single command to compile everything at once I want to compile
    > each source file to an object file and then link them all together. In
    > case your are curious why, if I have 10,000 source files I don't want to
    > recompile all of them if I make a change to just one file.


    Okay; so far that's all irrelevant. 'make' is off-topic here,
    and the compiler doesn't care how it's invoked anyway. Make or
    no make, it's all the same to it.

    > If I have two files that #include the same header file, the make command
    > will compile the frst file, the compiler will see that this is the first
    > time we have included the header and #include it. When I compile the
    > second file, this is a new run of the compiler so the compiler will thikn
    > we are accessing the header file for the first time, again.


    Yes, of course. That's the way most operating systems work -- program
    data is "forgotten" between runs of the same program.

    > When we link
    > the object files from file one and file two there will be trouble.


    Why? What kind of trouble are you experiencing?


    -Arthur,
    sounds like a case of "Doctor, it hurts when I do this..."
     
    Arthur J. O'Dwyer, Sep 25, 2003
    #7
  8. sieg1974

    Tom Zych Guest

    "Arthur J. O'Dwyer" wrote:

    > [Tangential: Someone else suggested #defining DUTILS_H instead.
    > That's harmless in this case, but stupid in general. Don't listen
    > to that person.]


    Um, why?

    --
    Tom Zych
    This is a fake email address to thwart spammers.
    Real address: echo '' | rot13
     
    Tom Zych, Sep 26, 2003
    #8
  9. sieg1974

    Tom Zych Guest

    Robert Stankowic wrote:

    > "Tom Zych" <> schrieb im Newsbeitrag
    > news:...


    > > #ifndef DUTILS_H /* note changed macro name */


    > Why did you change it?
    > AFAIK macro-names starting with upper case 'E' are reserved, so prefixing
    > the macro-name with H_ puts you on the safe side.


    I was going to say, that's how the standard headers on my system do
    it, but checking, I see they actually do _STDIO_H and such. I want
    to see why Arthur says it's stupid.

    --
    Tom Zych
    This is a fake email address to thwart spammers.
    Real address: echo '' | rot13
     
    Tom Zych, Sep 26, 2003
    #9
  10. sieg1974

    Kevin Easton Guest

    Tom Zych <> wrote:
    > Robert Stankowic wrote:
    >
    >> "Tom Zych" <> schrieb im Newsbeitrag
    >> news:...

    >
    >> > #ifndef DUTILS_H /* note changed macro name */

    >
    >> Why did you change it?
    >> AFAIK macro-names starting with upper case 'E' are reserved, so prefixing
    >> the macro-name with H_ puts you on the safe side.

    >
    > I was going to say, that's how the standard headers on my system do
    > it, but checking, I see they actually do _STDIO_H and such. I want
    > to see why Arthur says it's stupid.


    It's irrelevant anyway (you can't use names like _DUTILS_H yourself
    either) - the implementation headers are allowed to do things that your
    code isn't. The reason for this is to give the implmentation (compiler
    and libraries) a namespace in which it can define identifiers or
    keywords with whatever semantics it wants to / needs to.

    - Kevin.
     
    Kevin Easton, Sep 26, 2003
    #10
  11. "Tom Zych" <> schrieb im Newsbeitrag
    news:...
    > Robert Stankowic wrote:
    >
    > > "Tom Zych" <> schrieb im Newsbeitrag
    > > news:...

    >
    > > > #ifndef DUTILS_H /* note changed macro name */

    >
    > > Why did you change it?
    > > AFAIK macro-names starting with upper case 'E' are reserved, so

    prefixing
    > > the macro-name with H_ puts you on the safe side.

    >
    > I was going to say, that's how the standard headers on my system do
    > it, but checking, I see they actually do _STDIO_H and such. I want
    > to see why Arthur says it's stupid.
    >


    Well, stupid is a hard word (Hi, Arthur, no offense intended :)).
    Just something like
    #ifndef H_DUTILS_H_INCLUDED /*note the H_*/ protects me from inadvertent
    clashing with the implementations' namespace (uppercase E followed by
    another uppercase letter in macro-names (among others) is reserved for the
    implementation)
    So the original makro-name was better than your correction.
     
    Robert Stankowic, Sep 26, 2003
    #11
  12. sieg1974

    Tom Zych Guest

    Robert Stankowic wrote:

    > Well, stupid is a hard word (Hi, Arthur, no offense intended :)).
    > Just something like
    > #ifndef H_DUTILS_H_INCLUDED /*note the H_*/ protects me from inadvertent
    > clashing with the implementations' namespace (uppercase E followed by
    > another uppercase letter in macro-names (among others) is reserved for the
    > implementation)
    > So the original makro-name was better than your correction.


    Oh, I was thinking "E_*", not "E*". Is that general, or just your
    implementation? Don't recall hearing of that before.

    --
    Tom Zych
    This is a fake email address to thwart spammers.
    Real address: echo '' | rot13
     
    Tom Zych, Sep 26, 2003
    #12
  13. On Fri, 26 Sep 2003, Tom Zych wrote:
    >
    > Robert Stankowic wrote:
    > >
    > > Well, stupid is a hard word (Hi, Arthur, no offense intended :)).


    Ditto. ;-)

    > > Just something like
    > > #ifndef H_DUTILS_H_INCLUDED /*note the H_*/ protects me from inadvertent
    > > clashing with the implementations' namespace (uppercase E followed by
    > > another uppercase letter in macro-names (among others) is reserved for the
    > > implementation)
    > > So the original macro-name was better than your correction.

    >
    > Oh, I was thinking "E_*", not "E*". Is that general, or just your
    > implementation? Don't recall hearing of that before.


    From N869:

    7.26.3 Errors <errno.h>

    [#1] Macros that begin with E and a digit or E and an
    uppercase letter (possibly followed by any combination of
    digits, letters, and underscore) may be added to the
    declarations in the <errno.h> header.

    Around the same section in N869, you can find the other reserved
    identifiers in C99; as well as str*, mem*, is* and to*, they include
    E*, PRI*, SCN*, LC_*, SIG*, int*_t, and wcs* [where the asterisk
    represents various -- but not all -- combinations of characters].
    The last of these is the only one, AFAIK, of which you really have to
    beware; the rest are only reserved for use as macros #defined in certain
    headers (so if you don't include the headers I think you're safe).

    So the following code (in two files) will cause undefined behavior:


    ==foo.c==
    #include <errno.h>
    #include "evil.h"
    ...

    ==evil.h==
    #ifndef EVIL_H
    #define EVIL_H
    ...
    #endif


    but I believe it would be safe to write

    ==foo.c==
    #include "evil.h"
    #undef EVIL_H
    #include <errno.h>
    ...

    ==evil.h==
    #ifndef EVIL_H
    #define EVIL_H
    ...
    #endif

    That's a little silly, and becomes implausible when
    you're dealing with medium-sized projects. Much easier
    to follow a consistent, safe rule from the start.

    -Arthur
     
    Arthur J. O'Dwyer, Sep 26, 2003
    #13
  14. sieg1974

    pete Guest

    Tom Zych wrote:
    >
    > Robert Stankowic wrote:
    >
    > > "Tom Zych" <> schrieb im Newsbeitrag
    > > news:...

    >
    > > > #ifndef DUTILS_H /* note changed macro name */

    >
    > > Why did you change it?
    > > AFAIK macro-names starting with upper case 'E' are reserved,
    > > so prefixing
    > > the macro-name with H_ puts you on the safe side.

    >
    > I was going to say, that's how the standard headers on my system do
    > it, but checking, I see they actually do _STDIO_H and such. I want
    > to see why Arthur says it's stupid.


    I think you're missing the point.
    The way that the implementation does it,
    is the way that you're *not* supposed to do it.

    No implementation comes with:
    #define H_FILENAME
     
    pete, Sep 26, 2003
    #14
  15. sieg1974

    Kevin Easton Guest

    Tom Zych <> wrote:
    > Robert Stankowic wrote:
    >
    >> Well, stupid is a hard word (Hi, Arthur, no offense intended :)).
    >> Just something like
    >> #ifndef H_DUTILS_H_INCLUDED /*note the H_*/ protects me from inadvertent
    >> clashing with the implementations' namespace (uppercase E followed by
    >> another uppercase letter in macro-names (among others) is reserved for the
    >> implementation)
    >> So the original makro-name was better than your correction.

    >
    > Oh, I was thinking "E_*", not "E*". Is that general, or just your
    > implementation? Don't recall hearing of that before.


    In general. They're only reserved if you've included errno.h, but if
    you're writing a general header file you can't be sure if any file that
    includes it isn't also going to include errno.h. Quoting from N869:

    7.26.3 Errors <errno.h>
    Macros that begin with E and a digit or E and an uppercase letter
    (possibly followed by any combination of digits, letters, and
    underscore) may be added to the declarations in the <errno.h> header.

    7.1.3 Reserved identifiers
    1 Each header declares or defines all identifiers listed in its
    associated subclause, and optionally declares or defines identifiers
    listed in its associated future library directions subclause and
    identifiers which are always reserved either for any use or for use as
    file scope identifiers.

    2 No other identifiers are reserved. If the program declares or defines
    an identifier in a context in which it is reserved (other than as
    allowed by 7.1.4), or defines a reserved identifier as a macro name,
    the behavior is undefined.

    - Kevin.
     
    Kevin Easton, Sep 26, 2003
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dave
    Replies:
    2
    Views:
    359
    Jack Klein
    Nov 3, 2003
  2. Ron
    Replies:
    3
    Views:
    318
    Jack Klein
    Nov 12, 2003
  3. Steven T. Hatton
    Replies:
    7
    Views:
    2,362
    Howard
    Jun 3, 2004
  4. Victor Bazarov
    Replies:
    0
    Views:
    434
    Victor Bazarov
    May 10, 2006
  5. Mark A. Gibbs
    Replies:
    0
    Views:
    3,544
    Mark A. Gibbs
    May 10, 2006
Loading...

Share This Page