Thread: Writing a macro to compare two numbers?

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

3. Originally Posted by RichSelian
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. Originally Posted by CommonTater
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.

5. Originally Posted by grumpy
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. An idea which grumpy points out its limitation...

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

8. And people wonder why I don't use macros...

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

11. Originally Posted by Salem
Upgrade to C99 and use inline functions if it really bothers you.
Switch to C++ and write a function template

12. #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. 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. 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?

15. Originally Posted by anduril462
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.
Originally Posted by Bayint Naung
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.

Popular pages Recent additions