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.


    G G, Sep 15, 2013
    1. Advertisements

  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, Sep 15, 2013
    1. Advertisements

  3. 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
    and in header2 you should have another unique something like
    #ifndef HEADER2_GUARD
    #define HEADER2_GUARD
    /*the body of the header
    Barry Schwarz, Sep 15, 2013
  4. G G

    James Kuyper Guest

    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

    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
    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, Sep 15, 2013
  5. G G

    G G Guest


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


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


    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>

    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
  6. G G

    Joe Pfeiffer Guest

    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

    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
  7. G G

    James Kuyper Guest

    I disagree.
    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.
    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

    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
    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, Sep 16, 2013
  8. 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?
    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.
    Barry Schwarz, Sep 16, 2013
  9. 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
  10. (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

    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


    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

    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, Sep 16, 2013
  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, Sep 17, 2013
  12. No, it wouldn't. Those were really awful examples.
    Edward A. Falk, Sep 25, 2013
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.