C-preprocessor macro question

Discussion in 'C Programming' started by Charlie Zender, Dec 24, 2003.

  1. Hi,

    I want to have a CPP macro that tests the value of a token and
    returns the string "No" if the token is undefined (or 0) and
    returns "Yes" if the token is defined (non-zero).

    Then I can have C code that self-diagnoses its configuration with,
    e.g.,

    #define TKN2YESNO(x) ((x)==0 ? ("No"):("Yes"))
    (void)fprintf(stderr,"The token FOO is defined: %s",TKN2YESNO(FOO));
    (void)fprintf(stderr,"The token BAR is defined: %s",TKN2YESNO(BAR));

    However, my definition of TKN2YESNO() does not work.
    The GCC compiler on Linux flags an when I invoke TKN2YESNO() as above:

    nco_scm.c:195: error: `FOO' undeclared (first use in this function)

    Any help in understanding the cause of this error and how to correct
    it to achieve the desired functionality would be appreciated!

    Thanks,
    Charlie
    --
    Charlie Zender, , (949) 824-2987, Department of Earth
    System Science, University of California, Irvine CA 92697-3100
    Visiting NCAR 12/13/03--1/17/04: ***********************************
    Voice/FAX: (303) 497-1724/1348, Office: Mesa Lab 259b **************
     
    Charlie Zender, Dec 24, 2003
    #1
    1. Advertising

  2. On Tue, 23 Dec 2003, Charlie Zender wrote:
    >
    > I want to have a CPP macro that tests the value of a token and
    > returns the string "No" if the token is undefined (or 0) and
    > returns "Yes" if the token is defined (non-zero).


    In general I believe this is impossible, but someone may yet
    prove me wrong. To what would your hypothetical macro evaluate in
    the following "corner cases"?

    #define FOO
    #define FOO 0
    #define FOO 0+0
    #define FOO "bar"
    #define FOO +
    #define FOO if

    Should it yield "Yes", "No", some other defined result, or would
    it be allowed to crash completely? Or are you just looking for a
    macro to yield "Yes" or "No" based on the integer value of a
    #defined or un#defined macro -- in that case, I think you might
    be looking for something as simple as

    #define P(x) x
    #define YESNO(foo) (P(foo)+0)? "Yes": "No")

    #define foo 42 yields "Yes"
    #define foo 0 yields "No"
    #define foo yields "No"

    but it may not like complicated expressions.


    > Then I can have C code that self-diagnoses its configuration with,
    > e.g.,
    >
    > #define TKN2YESNO(x) ((x)==0 ? ("No"):("Yes"))
    > (void)fprintf(stderr,"The token FOO is defined: %s",TKN2YESNO(FOO));
    > (void)fprintf(stderr,"The token BAR is defined: %s",TKN2YESNO(BAR));
    >
    > However, my definition of TKN2YESNO() does not work.
    > The GCC compiler on Linux flags an when I invoke TKN2YESNO() as above:
    >
    > nco_scm.c:195: error: `FOO' undeclared (first use in this function)


    This Won't Work (TM). If the token 'FOO' is *completely* undefined,
    it won't macro-expand to anything, and you'll be left with 'FOO',
    which the compiler will then treat like any other identifier -- as
    if it were a variable name or something. And you'll get errors.
    If this is what you want, you'll have to be a *lot* more specific
    about what counts as "defined" and what doesn't, and maybe someone
    will be nice enough to whip up a hack like the "month-day-year"
    preprocessor hack Martin Dickopp did in this thread:

    For example, you might get somewhere useful by stringizing the
    thing. Other than that, I think you're stuck with

    #if defined(foo) && (foo != 0)
    ...
    #endif

    which is tedious.

    HTH,
    -Arthur
     
    Arthur J. O'Dwyer, Dec 24, 2003
    #2
    1. Advertising

  3. Charlie Zender

    Derk Gwen Guest

    Charlie Zender <> wrote:
    # Hi,
    #
    # I want to have a CPP macro that tests the value of a token and
    # returns the string "No" if the token is undefined (or 0) and
    # returns "Yes" if the token is defined (non-zero).

    As a macro processor, CPP is fatally crippled. In particular you cannot
    assume it will permit an #if or #ifdef within a #define. I would suggest
    using a widely available real macro processor, perhaps m4, or to use a
    scripting language like perl or Tcl as if a macro processor.

    --
    Derk Gwen http://derkgwen.250free.com/html/index.html
    Leave it to the Catholics to destroy existence.
     
    Derk Gwen, Dec 24, 2003
    #3
  4. Charlie Zender

    Richard Bos Guest

    Derk Gwen <> wrote:

    > Charlie Zender <> wrote:
    > # I want to have a CPP macro that tests the value of a token and
    > # returns the string "No" if the token is undefined (or 0) and
    > # returns "Yes" if the token is defined (non-zero).
    >
    > As a macro processor, CPP is fatally crippled.


    As a C preprocessor, though, the C preprocessor is, if anything,
    dangerously overpowered and therefore prone to abuse. As a second-tier
    programming language to munge the outcome of your main programming
    language it lacks ****-around-ability power, true, but that's probably
    just as well.

    > In particular you cannot assume it will permit an #if or #ifdef
    > within a #define.


    Actually, you can (indeed, must) assume that it will _not_ permit
    complete preprocessing commands within the expansion of a preprocessor
    macro.

    Richard
     
    Richard Bos, Dec 24, 2003
    #4
    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. qazmlp
    Replies:
    18
    Views:
    571
    Martin Dickopp
    Aug 16, 2003
  2. Cronus
    Replies:
    1
    Views:
    718
    Paul Mensonides
    Jul 15, 2004
  3. qazmlp
    Replies:
    18
    Views:
    879
    Martin Dickopp
    Aug 16, 2003
  4. Eric

    preprocessor q: impossible macro?

    Eric, Jul 18, 2005, in forum: C Programming
    Replies:
    21
    Views:
    687
  5. recvfrom
    Replies:
    1
    Views:
    306
    A. Sinan Unur
    Mar 20, 2006
Loading...

Share This Page