// Slimey cheap key comparator.
int32 cmpkey(const void *key1, const void *key2) {
return (int32)((intptr_t)key1 - (intptr_t)key2);
}
Any C programmer's spidey sense should tingle when they see a ternary comparison function implemented like this. Let's look at the canonical example: int intcmp(int x, int y) { return x - y; }
It seems perfectly fine. After all, cmp functions are usually allowed to return any signed number, not only -1, 0 or +1. But what happens if x is INT_MAX and y is INT_MIN? You get signed integer overflow. That's bad. In theory, it's really, really bad because signed integer overflow in C is undefined, so it could launch nuclear missiles, segfault, or give a compiler like GCC total license to fuck with your code in all kinds of ways that are hard to imagine. In practice, on 2's complement machines, it's just really bad since INT_MAX - INT_MIN = -1 doesn't have the right sign.Returning to Cliff's code, since he's only using the cmp function for equality and not ordering, the overflow problem doesn't manifest itself. If he were using it for ordering in a sorted array or search tree, you might think that this wouldn't cause a bug as long as all he needed was a consistent ordering rather than any particular one. Well, you'd be wrong, because intcmp violates transitivity. Mathematically speaking, INT_MIN+1 < 0 < INT_MAX. According to intcmp, INT_MIN+1 < 0 and 0 < INT_MAX but INT_MIN+1 > INT_MAX. This breaks the invariants of your sorting and search tree code, so all bets are off.
The solution? Do the simple thing:
int intcmp(int x, int y) { return x < y ? -1 : x > y ? +1 : 0; }
Your compiler can turn this into a few branchless instructions with a single CMP.