Preprocessor commands usage.

Discussion in 'C Programming' started by G G, Sep 15, 2013.

  1. G G

    G G Guest

    #include <stdio.h> // for printf()
    int main (void)
    {
    #define FNORD hello
    int FNORD = 23;
    printf ("hello, your number today is %d\n", hello);
    #define NOBODY_HOME
    static unsigned NOBODY_HOME int thing = 42;
    printf ("thing, your number today is %d\n", thing);

    // This is actually a dangerous way to do this. See
    // the section about macro hygiene.

    #define SUM(x, y) x + y
    int value = SUM(23, 42);
    printf ("value, your number today is %d\n", value);
    return 0;

    } // main

    This code comes from, Advanced Mac OS Programming.

    I understand the author is trying to demonstrate the preprocessor expansion but
    this would not really be done would it.

    for example :

    #define FNORD hello
    int FNORD = 23;
    printf ("hello, your number today is %d\n", hello);

    is this unusual or should i expect to see a lot of this method, style, in processor
    code. (leaning c now) in this example, i'm talking about defining FNORD to hello
    then assigning 23 to FNORD. so far, and my experience is limited, i have only
    seen #define to replace text, or some type of macro definition. i have seen
    an assignment allowed in the program, as done here.

    Thanks,

    g.
    G G, Sep 15, 2013
    #1
    1. Advertising

  2. G G

    G G Guest

    On Sunday, September 15, 2013 9:04:23 AM UTC-4, Dr Nick wrote:

    Thanks Dr. Nick

    i have anther question.
    another example:
    the author is describing in this example the problem of multiple inclusion of
    header files. he explains that header files include some header files included in
    other header files. (well, he actually says it better than the way i wrote it) so, some
    header file are being included more than once... like cdefs.h

    The following is the example code:

    #include <fcntl.h> // for open()
    #include <ulimit.h> // for ulimit()
    #include <pthread.h> // for pthread_create()
    #include <dirent.h> // for opendir()

    int main (void) {
    // nobody home
    return 0;
    } // main

    his presented solution is to use the #ifndef directive.

    // include-guard.h -- making sure the contents of the header
    // are included only once.
    #ifndef INCLUDE_GUARD_H
    #define INCLUDE_GUARD_H

    // Put the real header contents here.

    #endif // INCLUDE_GUARD_H

    my question is, wouldn't each header file that you did not want to include
    twice or more have to appear where the "//Put the real header content here" goes.
    in other words doing the following would not eliminate the problem of cdefs.h
    being included more than once.
    _______________________________________________________________

    // include-guard.h -- making sure the contents of the header
    // are included only once.
    #ifndef INCLUDE_GUARD_H
    #define INCLUDE_GUARD_H

    // Put the real header contents here.

    #include <fcntl.h> // for open()
    #include <ulimit.h> // for ulimit()
    #include <pthread.h> // for pthread_create()
    #include <dirent.h> // for opendir()

    #endif // INCLUDE_GUARD_H


    int main (void) {
    // nobody home
    return 0;
    } // main
    ___________________________________________________________________

    g.
    G G, Sep 15, 2013
    #2
    1. Advertising

  3. On Sun, 15 Sep 2013 07:29:21 -0700 (PDT), G G <>
    wrote:

    >On Sunday, September 15, 2013 9:04:23 AM UTC-4, Dr Nick wrote:
    >
    >Thanks Dr. Nick
    >
    >i have anther question.
    >another example:
    >the author is describing in this example the problem of multiple inclusion of
    >header files. he explains that header files include some header files included in
    >other header files. (well, he actually says it better than the way i wrote it) so, some
    >header file are being included more than once... like cdefs.h
    >
    >The following is the example code:
    >
    >#include <fcntl.h> // for open()
    >#include <ulimit.h> // for ulimit()
    >#include <pthread.h> // for pthread_create()
    >#include <dirent.h> // for opendir()
    >
    >int main (void) {
    > // nobody home
    > return 0;
    >} // main
    >
    >his presented solution is to use the #ifndef directive.
    >
    >// include-guard.h -- making sure the contents of the header
    >// are included only once.
    >#ifndef INCLUDE_GUARD_H
    >#define INCLUDE_GUARD_H
    >
    >// Put the real header contents here.
    >
    >#endif // INCLUDE_GUARD_H
    >
    >my question is, wouldn't each header file that you did not want to include
    >twice or more have to appear where the "//Put the real header content here" goes.
    >in other words doing the following would not eliminate the problem of cdefs.h
    >being included more than once.
    >_______________________________________________________________
    >
    >// include-guard.h -- making sure the contents of the header
    >// are included only once.
    >#ifndef INCLUDE_GUARD_H
    >#define INCLUDE_GUARD_H
    >
    >// Put the real header contents here.
    >
    >#include <fcntl.h> // for open()
    >#include <ulimit.h> // for ulimit()
    >#include <pthread.h> // for pthread_create()
    >#include <dirent.h> // for opendir()
    >
    >#endif // INCLUDE_GUARD_H
    >
    >
    >int main (void) {
    > // nobody home
    > return 0;
    >} // main


    It is likely that each of the standard headers already has its own
    guard. What I hope the author was trying to convey is that your
    headers should do the same. If you have
    #include "header1.h"
    #include "header2.h"
    then in header1.h you should have something unique like
    #ifndef HEADER1_GUARD
    #define HEADER1_GUARD
    /*the body of the header
    #endif
    and in header2 you should have another unique something like
    #ifndef HEADER2_GUARD
    #define HEADER2_GUARD
    /*the body of the header
    #endif

    --
    Remove del for email
    Barry Schwarz, Sep 15, 2013
    #3
  4. G G

    James Kuyper Guest

    On 09/15/2013 10:29 AM, G G wrote:
    > On Sunday, September 15, 2013 9:04:23 AM UTC-4, Dr Nick wrote:
    >
    > Thanks Dr. Nick
    >
    > i have anther question.
    > another example:
    > the author is describing in this example the problem of multiple inclusion of
    > header files. he explains that header files include some header files included in
    > other header files. (well, he actually says it better than the way i wrote it) so, some
    > header file are being included more than once... like cdefs.h
    >
    > The following is the example code:
    >
    > #include <fcntl.h> // for open()
    > #include <ulimit.h> // for ulimit()
    > #include <pthread.h> // for pthread_create()
    > #include <dirent.h> // for opendir()
    >
    > int main (void) {
    > // nobody home
    > return 0;
    > } // main
    >
    > his presented solution is to use the #ifndef directive.
    >
    > // include-guard.h -- making sure the contents of the header
    > // are included only once.
    > #ifndef INCLUDE_GUARD_H
    > #define INCLUDE_GUARD_H
    >
    > // Put the real header contents here.
    >
    > #endif // INCLUDE_GUARD_H
    >
    > my question is, wouldn't each header file that you did not want to include
    > twice or more have to appear where the "//Put the real header content here" goes.
    > in other words doing the following would not eliminate the problem of cdefs.h
    > being included more than once.
    > _______________________________________________________________
    >
    > // include-guard.h -- making sure the contents of the header
    > // are included only once.
    > #ifndef INCLUDE_GUARD_H
    > #define INCLUDE_GUARD_H
    >
    > // Put the real header contents here.
    >
    > #include <fcntl.h> // for open()
    > #include <ulimit.h> // for ulimit()
    > #include <pthread.h> // for pthread_create()
    > #include <dirent.h> // for opendir()
    >
    > #endif // INCLUDE_GUARD_H


    You misunderstand the example. Header guards are meant to be put inside
    a header file, not in the main code. The words "include-guard.h" at the
    start of the example indicated that the example code belongs INSIDE of
    the file named "include-garde.h".

    Let me give an example from my own code.:

    Excerpt from GEO_ephem_attit.c:
    ...
    #include "GEO_earth.h"
    #include "GEO_input.h"
    #include "GEO_product.h"
    ...

    Every one of those three header files contains the following line:
    #include "mapi.h"

    Excerpt from mapi.h:
    #ifndef MAPI_H
    #define MAPI_H
    // The main header contents
    #endif

    When GEO_ephem_attit.c is compiled,

    #include "GEO_earth.h"

    is replaced by the contents of GEO_earth.h. Going through those lines,
    the compiler finds

    #include "mapi.h"

    and replaces that line with a copy of mapi.h. As a result, MAPI_H gets
    #defined, and all of the declarations and #definitions from mapi.h are
    processed.
    When the compiler gets to

    #include "GEO_input.h"

    it replaces that line with a copy of GEO_input.h. Going through those
    lines, the compiler finds another line that says

    #include "mapi.h"

    and that line is also replaced by the contents of mapi.h. However, this
    time, MAPI_H is already #defined, and as a result the lines between the
    #ifndef and the #endif in mapi.h get skipped over. That's good, because
    many of those lines would cause identifiers to be declared or #defined
    more than once.

    The same thing happens when expanding

    #include GEO_product.h
    --
    James Kuyper
    James Kuyper, Sep 15, 2013
    #4
  5. G G

    G G Guest

    ah.

    i think i understand the examples you and Barry have provided.

    thanks.

    main.m
    |
    |
    -----------------------------------------------------------------------------
    | | | |
    fcntl.h ulimit.h pthread.h dirent.h
    | | | |
    | | / | \ | \
    _types.h cdefs.h _types.h time.h cdefs.h _types.h cdefs.h

    etc.

    an example to check understanding:

    so, in a headed file (well any file where header files are included) that iwould create i would put #ifndef for cdefs.h if i wanted to include it only once. doing so would defined it once, as the compiler evaluates the other#include(s), of any other header file, cdefs.h would not be included againeven though other C language standard header files may call for cdefsh to be include in them.

    #ifndef <cdefs.h>
    #define <cdefs.h>
    #include <fcntl.h>
    #include <ulimit.h>
    #include <pthread.h>
    #include <dirent.h>
    #endif

    it is necessary to review a tree of included files and add header files to a #ifndef ... #endif that might be included more than once?

    thanks again.
    G G, Sep 15, 2013
    #5
  6. G G

    Joe Pfeiffer Guest

    G G <> writes:

    > ah.
    >
    > i think i understand the examples you and Barry have provided.
    >
    > thanks.
    >
    > main.m
    > |
    > |
    > -----------------------------------------------------------------------------
    > | | | |
    > fcntl.h ulimit.h pthread.h dirent.h
    > | | | |
    > | | / | \ | \
    > _types.h cdefs.h _types.h time.h cdefs.h _types.h cdefs.h
    >
    > etc.
    >
    > an example to check understanding:
    >
    > so, in a headed file (well any file where header files are included) that i would create i would put #ifndef for cdefs.h if i wanted to include it only once. doing so would defined it once, as the compiler evaluates the other #include(s), of any other header file, cdefs.h would not be included again even though other C language standard header files may call for cdefsh to be include in them.
    >
    > #ifndef <cdefs.h>
    > #define <cdefs.h>
    > #include <fcntl.h>
    > #include <ulimit.h>
    > #include <pthread.h>
    > #include <dirent.h>
    > #endif
    >
    > it is necessary to review a tree of included files and add header files to a #ifndef ... #endif that might be included more than once?
    >
    > thanks again.


    Not quite -- when you create a header file, you take the steps to
    protect your own file from being multiply included. All the header
    files under /usr/include/ are supposed to be so protected (but if
    somebody shows me an example of one that isn't, I certainly won't be
    surprised). If I look at /usr/include/fcntl.h I find (right after the
    copyright notice)

    #ifndef _FCNTL_H
    #define _FCNTL_H 1

    and I find at the end of the file

    #endif /* fcntl.h */

    So you can safely do something in your code that ends up looking like

    #include <fcntl.h>
    #include <fcntl.h>

    and the first time it's included everything in it will be defined
    appropriately, but the second time nothing will happen.

    You don't need to worry about the possibility of #including <fcntl.h>
    twice, as the file itself protects you from bad things happening if you
    do.

    Note that your

    #ifndef <cdefs.h>

    won't compile, since you have to have an identifier there, not something
    with <> around it.
    Joe Pfeiffer, Sep 16, 2013
    #6
  7. G G

    James Kuyper Guest

    On 09/15/2013 06:30 PM, G G wrote:
    > ah.
    >
    > i think i understand the examples you and Barry have provided.


    I disagree.

    > an example to check understanding:
    >
    > so, in a headed file (well any file where header files are included)
    > that i would create i would put #ifndef for cdefs.h if i wanted to
    > include it only once. doing so would defined it once, as the compiler
    > evaluates the other #include(s), of any other header file, cdefs.h
    > would not be included again even though other C language standard
    > header files may call for cdefsh to be include in them.


    No. You only put include guards in header files, you never place them in
    your *.c files. The header guard goes inside the header file that it
    gaurds. The header guard DOES not prevent the header file from being
    #included multiple times. What it does is make sure, if the header file
    does get #included multiple times, that the main part of the header file
    only gets processed the first time.

    cdefs.h is not a C standard header - the only C standard header that you
    mentioned was time.h. Most of the others are POSIX headers, but cdefs.h
    seems to be linux-specific. There's no _types.h file on my system, so I
    have no idea what that is.

    > #ifndef <cdefs.h>
    > #define <cdefs.h>
    > #include <fcntl.h>
    > #include <ulimit.h>
    > #include <pthread.h>
    > #include <dirent.h>
    > #endif


    In addition to putting your header guard in the wrong location, you've
    also got the wrong syntax. There's an example of the correct syntax
    inside of cdefs.h on my system, there's the following lines:

    #ifndef _SYS_CDEFS_H
    #define _SYS_CDEFS_H
    ....
    #endif

    Note that it's up to the designer of the header file to decide what name
    to use for the include guard; it doesn't have to have any connection to
    the actual header file name.

    Note also that identifiers starting with an underscore followed by a
    capital letter are reserved - that means you can't use them. The reason
    you can't use them is so that the implementors of the C standard library
    CAN use them. The use of such names in cdefs.h suggests either that it
    is provided as an extension by the same people who provided the C
    standard library, or that a serious mistake was made. YOU should never
    use such names in your own

    > it is necessary to review a tree of included files and add header
    > files to a #ifndef ... #endif that might be included more than once?


    No, it's not necessary to do any such analysis. You should put a header
    guard in every header file you write. When I write header files, the
    first thing I put in them is the header guard, including the following
    #endif. I fill in the body of the header later.
    --
    James Kuyper
    James Kuyper, Sep 16, 2013
    #7
  8. On Sun, 15 Sep 2013 15:30:43 -0700 (PDT), G G <>
    wrote:

    >ah.
    >
    >i think i understand the examples you and Barry have provided.
    >
    >thanks.
    >
    > main.m
    > |
    > |
    >-----------------------------------------------------------------------------
    > | | | |
    >fcntl.h ulimit.h pthread.h dirent.h
    > | | | |
    > | | / | \ | \
    >_types.h cdefs.h _types.h time.h cdefs.h _types.h cdefs.h
    >
    >etc.
    >
    >an example to check understanding:
    >
    >so, in a headed file (well any file where header files are included) that i would create i would put #ifndef for cdefs.h if i wanted to include it only once. doing so would defined it once, as the compiler evaluates the other #include(s), of any other header file, cdefs.h would not be included again even though other C language standard header files may call for cdefsh to be include in them.


    NO.
    1 - You only put a guard INSIDE a header file you create.
    2 - You do not worry about system headers.
    3 - You do not depend on someone using your header (that means you
    too) taking precautions in the source file containing the #include
    directive. By virtue of step 1, the header file protects itself,
    unless a perverse user issues the #undef directive (in which case he
    deserves what he gets).
    4 - Just out of curiosity, since several header files need
    _types.h, how do you think any code in your source file could insure
    _types.h is included exactly once when including more than one
    "parent" header?

    >#ifndef <cdefs.h>
    >#define <cdefs.h>
    >#include <fcntl.h>
    >#include <ulimit.h>
    >#include <pthread.h>
    >#include <dirent.h>
    >#endif
    >
    >it is necessary to review a tree of included files and add header files to a #ifndef ... #endif that might be included more than once?


    It is not necessary (and not recommended) to review system headers.
    They frequently contain system dependent constructs which you would be
    wise not to emulate. The C and posix standards tell you everything
    you need to know to use them correctly for most tasks.

    It is definitely unnecessary to construct include trees for system
    headers. Whether you need to do so for your headers is a decision
    only you can make.

    --
    Remove del for email
    Barry Schwarz, Sep 16, 2013
    #8
  9. In article <l15ke1$i3s$>,
    James Kuyper <> sputtered:
    ....
    >There's no _types.h file on my system, so I have no idea what that is.


    You do know about this newfangled thing called "Google", don't you?

    It's really cool. It allows you to learn about all sorts of stuff that you
    don't have direct physical access to. You really should check it out.

    --
    - Since the shootings on Friday, the ultra-defensive [maybe wrongly
    - hyphenated, but that would be fitting] Roy "News" LIEberman has posted
    - at least 90 times, and almost every single post is about his obsessive
    - knee-jerk loonball [wacko] gun politics. How much longer before the
    - authorities [police] finally disable the trip wires and confiscate the
    - arsenal in his St. Louie hovel?

    So true. So true.
    Kenny McCormack, Sep 16, 2013
    #9
  10. G G <> writes:
    > i think i understand the examples you and Barry have provided.
    >
    > thanks.
    >
    > main.m
    > |
    > |
    > -----------------------------------------------------------------------------
    > | | | |
    > fcntl.h ulimit.h pthread.h dirent.h
    > | | | |
    > | | / | \ | \
    > _types.h cdefs.h _types.h time.h cdefs.h _types.h cdefs.h
    >
    > etc.
    >
    > an example to check understanding:
    >
    > so, in a headed file (well any file where header files are included)
    > that i would create i would put #ifndef for cdefs.h if i wanted to
    > include it only once. doing so would defined it once, as the compiler
    > evaluates the other #include(s), of any other header file, cdefs.h
    > would not be included again even though other C language standard
    > header files may call for cdefsh to be include in them.
    >
    > #ifndef <cdefs.h>
    > #define <cdefs.h>
    > #include <fcntl.h>
    > #include <ulimit.h>
    > #include <pthread.h>
    > #include <dirent.h>
    > #endif
    >
    > it is necessary to review a tree of included files and add header
    > files to a #ifndef ... #endif that might be included more than once?


    (Please wrap your lines at 80 columns or less, preferably about 72.)

    No, I don't think you get it.

    First off, "#ifndef <cdefs.h>" is a syntax error; the argument of
    #ifndef must be a valid identifier, which <cdefs.h> is not.

    Each header has its own header guard; no other file has to be aware of
    it.

    For example, if you have a header file called "cdefs.h", then its first
    two lines should be something like:

    #ifndef H_CDEFS
    #define H_CDEFS

    and its last line should be

    #endif

    Any other file that needs to use the declarations in cdefs.h will
    simply use:

    #include "cdefs.h"

    (Note the use of "..." rather than <...>; the latter is for system
    headers.)

    That's about all there is to it. It's up to the author of each
    header file to pick a macro name that's unique to that file.

    The reason for header guards is to avoid having the same declaration
    appear more than once. A source file that includes "cdefs.h"
    might also include another header file that includes "cdefs.h".
    The #ifndef sequence guarantees that, no matter how many times
    "cdefs.h" is included directly or indirectly, its declarations will
    appear only once.

    Incidentally, your picture refers to a file called "main.m".
    The ".m" suffix is commonly used for Objective-C source files.
    If you're programming on Objective-C, you're in the wrong place;
    it's very similar to C in many ways, but there might be differences
    in the way headers are handled.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Working, but not speaking, for JetHead Development, Inc.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Sep 16, 2013
    #10
  11. G G

    G G Guest

    ah, ok, i was way off in my thinking . i'm glad you guys explained header guards.

    thanks everyone.

    g.
    G G, Sep 17, 2013
    #11
  12. In article <>,
    G G <> wrote:
    >
    >I understand the author is trying to demonstrate the preprocessor expansion but
    >this would not really be done would it.


    No, it wouldn't. Those were really awful examples.

    --
    -Ed Falk,
    http://thespamdiaries.blogspot.com/
    Edward A. Falk, Sep 25, 2013
    #12
    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. Cronus
    Replies:
    1
    Views:
    667
    Paul Mensonides
    Jul 15, 2004
  2. Ben Pfaff

    Re: man pages for C commands (GCC commands)

    Ben Pfaff, Jun 24, 2003, in forum: C Programming
    Replies:
    4
    Views:
    3,968
    Thomas Stegen
    Jun 28, 2003
  3. Tim Stanka
    Replies:
    1
    Views:
    799
    Jeff Epler
    Aug 2, 2004
  4. Erik Leunissen

    String comparison in preprocessor commands

    Erik Leunissen, May 24, 2005, in forum: C Programming
    Replies:
    7
    Views:
    3,318
    Kenneth Brody
    May 29, 2005
  5. Juha Nieminen

    Preprocessor commands and whitespace

    Juha Nieminen, May 24, 2009, in forum: C++
    Replies:
    10
    Views:
    587
    Juha Nieminen
    May 27, 2009
Loading...

Share This Page