Do you need to #undef something that's already defined?

This is a discussion on Do you need to #undef something that's already defined? within the C Programming forums, part of the General Programming Boards category; If I have Code: #define PI 3.14159 To re-define PI, do I need to #undef it or can I just ...

  1. #1
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,046

    Do you need to #undef something that's already defined?

    If I have
    Code:
    #define PI 3.14159
    To re-define PI, do I need to #undef it or can I just put a new #define in?

    Someone on this board said that this was permissible:
    Code:
    #define PI 3.14159
    /*#undef PI*/
    #define PI 3.14159265358979
    But my compiler complains.

    Is the #undef required?
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  2. #2
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,484
    > Is the #undef required?
    Yes.

  3. #3
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,046
    Okay, thanks. That's what I thought.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Actually it seems that there are very specific situations where you can simply redefine.
    The benign redefinition of macros is allowed in Standard C and many other imple-
    mentations. That is, a macro may be redefined if the new definition is the same, token for
    token, as the existing definition. The redefinition must include whitespace in the same lo-
    cations as in the origional definition, although the particular whitespace characters can be
    different. We think programmers should avoid depending on benign redefinitions It is
    generally better style to have a single point of definition for all program entities, including
    macros. (Some older implementations of C may not allow any kind of redefinition.)
    Example:
    In the following definitions, the redefinition of NULL is allowed, but neither redefinition of
    FUNC is valid. (The first includes whitespace not in the origional definition, and the second
    changes two tokens.)

    #define NULL 0
    #define FUNC(x) x+4
    #define NULL /* null pointer */ 0
    #define FUNC(x) x + 4
    #define FUNC(y) y+4
    The above is quoted from page[s] 53/54 of "C: A Reference Manual, 5th edition." I remember reading a while back some place that any redefinition was allowed, but it seems as though that was incorrect, and there is (possibly at least) a specific usage that you can redefine it. Whatever reference I was reading implied that you could simply:
    Code:
    #define X 1
    #define X(y,z) y+z
    #define X 7.654
    And all would be legal. Apparently that's incorrect, and I can't remember where I was reading it. I haven't ever had the need to do so, so I never really paid much attention to it other than the passing read.

    The reference isn't clear however if the above is allowed. For example, while it says the above NULL redefinition is OK, it isn't overly clear if you could do:
    Code:
    #define FOO 0
    #define FOO 1
    #define FOO 2
    I'm not sure if they mean "tokens are the same" as "the 0 is the same in both definitions" or, "the x is renamed to y, so that's different", or both.

    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    old man
    Join Date
    Dec 2005
    Posts
    90
    According to the standard, redefinition is allowed, though with constraints (6.10.3 item 2). gcc emits a warning with the following code, but it compiles.

    Code:
    #include <stdio.h>
    
    #define X 2
    #define X 4
    
    int
    main (void)
    {
      printf ("\nX equals %d\n\n", X);
      return 0;
    }
    (gcc -Wall -Wextra -o redef redef.c)

    Of course, results may vary between compilers. It's no doubt wise to avoid code like this -- I'd go with the #undef personally.

  6. #6
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,006
    Some examples from C99:
    Code:
    5 EXAMPLE 3 To illustrate the rules for redefinition and reexamination, the sequence
    #define x 3
    #define f(a) f(x * (a))
    #undef x
    #define x 2
    #define g f
    #define z z[0]
    #define h g(~
    #define m(a) a(w)
    #define w 0,1
    #define t(a) a
    #define p() int
    #define q(x) x
    #define r(x,y) x ## y
    #define str(x) # x
    f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
    g(x+(3,4)-w) | h 5) & m
    (f)^m(m);
    p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };
    char c[2][6] = { str(hello), str() };
    results in
    f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
    f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);
    int i[] = { 1, 23, 4, 5, };
    char c[2][6] = { "hello", "" };
    
    8 EXAMPLE 6 To demonstrate the redefinition rules, the following sequence is valid.
    #define OBJ_LIKE (1-1)
    #define OBJ_LIKE /* white space */ (1-1) /* other */
    #define FUNC_LIKE(a) ( a )
    #define FUNC_LIKE( a )( /* note the white space */ \
    a /* other stuff on this line
    */ )
    But the following redefinitions are invalid:
    #define OBJ_LIKE (0) // different token sequence
    #define OBJ_LIKE (1 - 1) // different white space
    #define FUNC_LIKE(b) ( a ) // different parameter usage
    #define FUNC_LIKE(b) ( b ) // different parameter spelling
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,245
    Both the C++ standard and the 1989 C standard disallow redefinition of macros, except in cases where the redefinition is essentially the same as the previous definition (i.e. the macro has the same number of arguments, and the expansion of the macro is identical except for whitespace which will be ignored by the compiler, etc etc). I'm not sure offhand what the 1999 C standard says.

    The usual technique is to do a test
    Code:
    #ifdef PI
    #undef PI
    #endif
    #define PI 3.14159265358
    or (in cases where we can reasonably expect all definitions to represent logically the same thing) simply avoid redefining it;
    Code:
    #ifndef PI
    #define PI 3.14159265358
    #endif
    Incidentally, for manifest constants like PI, I'd probably compute them explicitly;
    Code:
    double my_double_constants(int value)
    {
         static char init = 0;
         static double constants[10];
         if (!init)
         {
                constants[0] = 4.0*atan(1.0);
                constants[1] = exp(1.0);
                /*  etc  */
         }
         return (value < 0 || value > 9) ? 0.0: constants[value];
    }
    
    #define PI my_double_constants(0)
    #define E my_double_constants(1)
    /* etc */
    This sort of technique computes all constants to the precision supported by your compiler/system, without unnecessary overhead of computing the values multiple times.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Linking problems in Visual Studio
    By h3ro in forum C++ Programming
    Replies: 5
    Last Post: 03-04-2008, 01:39 PM
  2. Round Robin Scheduling using c.
    By eclipt in forum C Programming
    Replies: 8
    Last Post: 12-28-2005, 03:58 PM
  3. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  4. DLL compiling question
    By Noose in forum Windows Programming
    Replies: 2
    Last Post: 12-16-2004, 06:16 AM
  5. Header files
    By borland_man in forum C++ Programming
    Replies: 14
    Last Post: 02-22-2002, 03:30 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21