Thread: Writing a macro to compare two numbers?

  1. #1
    Registered User
    Join Date
    Mar 2010
    Location
    China
    Posts
    74

    Writing a macro to compare two numbers?

    I want such a macro in my project: cmp(x, y) returns a positive number when x > y, a negative number when x < y, and 0 when x == y. of course I know the simplest way:
    Code:
    #define cmp(x, y) (((x) > (y)) ? 1 : (((x) == (y)) ? 0 : -1))
    but this cannot work properly for the code like cmp(x++, y++). Can this limit be fixed?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by RichSelian
    but this cannot work properly for the code like cmp(x++, y++). Can this limit be fixed?
    It depends. I would just adopt the convention of naming macros with uppercase letters as a warning to avoid such side effects.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by RichSelian View Post
    I want such a macro in my project: cmp(x, y) returns a positive number when x > y, a negative number when x < y, and 0 when x == y. of course I know the simplest way:
    Code:
    #define cmp(x, y) (((x) > (y)) ? 1 : (((x) == (y)) ? 0 : -1))
    but this cannot work properly for the code like cmp(x++, y++). Can this limit be fixed?
    Do you really care if it returns 1, 0 or -1? If all you care about is a positve, 0 or negative value you can simply return (x - y);
    Code:
    #define cmp(x, y) (x - y)

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by CommonTater View Post
    Do you really care if it returns 1, 0 or -1? If all you care about is a positve, 0 or negative value you can simply return (x - y);
    Code:
    #define cmp(x, y) (x - y)
    That won't work if x and y are both of unsigned integral type.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  5. #5
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by grumpy View Post
    That won't work if x and y are both of unsigned integral type.
    Picky picky picky!

    But you're right it won't work on unsigned values...
    But then it was only an example, intended to convey an idea...

  6. #6
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    An idea which grumpy points out its limitation...

  7. #7
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    And it won't work if y contains addition, subtraction, bitwise or logical operation, or x contains a bitwise or logical operation. You do want parenthesis around every argument in the macro. This the op did right.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  8. #8
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    And people wonder why I don't use macros...

  9. #9
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    One way
    Code:
    #define cmp(x, y) \
     ( \
        ( \
            assert(("Don't pass ++val or --val to a macro dufus", !((strstr(#x, "++")) || (strstr(#x, "--")) || (strstr(#y, "++")) || (strstr(#y, "--"))))), \
            (x) > (y) ? 1 : \
            (x) == (y) ? 0 : \
             -1\
        ) \
      )
    EDIT: Oh, the question was can it be fixed? Oh well, I'll leave it for anyone who wants to just detect it.

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Or extending it to anything which may have side effects, say
    cmp(putchar(x),putchar(y))

    Or using it on the wrong data types, say
    cmp("hello","world")
    which would produce the "right" answer half the time, but not for any good reason.

    Perhaps
    Code:
    #define cmp(result,x,y) do { int _x = x; int _y = y; \
          result = (_x) > (_y) ? 1 : (_x) == (_y) ? 0 : -1;  } while ( 0 )
    
    // use it like
    int result;
    cmp(result,x++,y++);
    It guarantees single evaluation, at the expense of a messy way of getting the result.
    Plus, the difficulty of coming up with suitable names for the temporary symbols (not to mention, their types).

    Upgrade to C99 and use inline functions if it really bothers you.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Salem
    Upgrade to C99 and use inline functions if it really bothers you.
    Switch to C++ and write a function template
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    Registered User
    Join Date
    Mar 2010
    Location
    China
    Posts
    74
    #define cmp(x, y) ((x)-(y)); This implementation may course overflow and return the wrong result.

    Any better idea? or am I going to write ugly int_cmp() short_cmp() char_cmp()/... using the inline function?

  13. #13
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    I don't think those functions are ugly personally, especially since they're exactly what's needed for using standard functions like bsearch, qsort and a variety of 3rd party libraries. But since you don't like them, you could at least reduce the number of them you have to write and just do signed_cmp and unsigned_cmp, that take and compare signed and unsigned ints respectively. Let the compiler automatically promote your char to an int and your unsigned short to an unsigned int. That reduces you down to two functions, or one if you don't need to handle unsigned numbers.

  14. #14
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    Wait for C1x they got type generic macro....C1X - Wikipedia, the free encyclopedia
    There's no easy way to 'fix' side effect.
    Just document not to use side-effect expression when using macro.
    I think even C++ (with operator loading).
    No one is going to write x++ > y++ ? Anyone?
    Last edited by Bayint Naung; 06-27-2011 at 05:23 PM.

  15. #15
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    Quote Originally Posted by anduril462 View Post
    I don't think those functions are ugly personally, especially since they're exactly what's needed for using standard functions like bsearch, qsort and a variety of 3rd party libraries. But since you don't like them, you could at least reduce the number of them you have to write and just do signed_cmp and unsigned_cmp, that take and compare signed and unsigned ints respectively. Let the compiler automatically promote your char to an int and your unsigned short to an unsigned int. That reduces you down to two functions, or one if you don't need to handle unsigned numbers.
    Those standard functions require function pointers, not macros.
    Quote Originally Posted by Bayint Naung View Post
    Wait for C1x they got type generic macro....C1X - Wikipedia, the free encyclopedia
    There's no easy way to 'fix' side effect.
    Just document not to use side-effect expression when using macro.
    I think even C++ (with operator loading).
    No one is going to write x++ > y++ ? Anyone?
    Overloaded operators are functions, so there is no problem.
    Last edited by King Mir; 06-27-2011 at 07:12 PM.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. writing a pair of numbers to an array
    By wankel in forum C Programming
    Replies: 53
    Last Post: 06-22-2009, 05:27 PM
  2. Writing unique numbers to an array
    By yardy in forum C Programming
    Replies: 6
    Last Post: 12-27-2006, 09:15 PM
  3. Writing a series of 8-bit numbers to disk with fwrite
    By thetinman in forum C Programming
    Replies: 16
    Last Post: 10-13-2006, 09:05 AM
  4. Help Writing My Own String Compare
    By djwicks in forum C Programming
    Replies: 4
    Last Post: 04-07-2005, 09:44 PM
  5. Replies: 2
    Last Post: 09-11-2002, 05:00 PM