How we must compare two integers?

The preferred way to write the non-branching code would be to use a local variable for the operands:

int icmp(const void *x, const void *y)
{
    int a = *(const int *)x;
    int b = *(const int *)y;
    return (a > b) - (a < b);
}

The expression is a common idiom in comparison functions, and if written using variables instead of in-place pointer dereferences it is rather readable too.

The code relies upon the fact that the result of a comparison using >, < or even == is of type int and either 1 or 0. This is required by the C standard - any compiler that generates values like 42 or -1 is by definition not a C compiler.

It is easy to see that max. one of a > b or a < b can be true at a given time, and the result is either 1 - 0, 0 - 1 or 0 - 0.

As to why branchless code - while compilers might generate the exact same code for both functions, they often do not. For example latest GCC and ICC both seem to generate a branch for the first function on x86-64, but branchless code with conditional execution for the latter. And to anyone who says that branches do not matter, then I refer you to the highest-voted QA ever on Stack Overflow.


Is it better to write like that?

I'd say no.

For performance; either it doesn't matter (likely for modern compilers), or it shouldn't be a separate function (and should be built into the code used for sorting), or you shouldn't be sorting at all (e.g. data sorted at creation and not sorted after creation).

For readability (code maintenance, chance of seeing errors in the original version, risk of introducing errors later) I'd prefer your original version; especially when working in a team, and especially when other team members are more familiar with 10 other programming languages that each has very different rules to C.

Specifically; I like this (because casts in actual code make things harder to read):

    int a = *(int*)x;
    int b = *(int*)y;

..and I would rewrite the rest to look like this:

    if (a > b) {
        return 1;
    }
    if (a < b) {
        return -1;
    }
    return 0;
}

..or to look like this:

    if (a > b) return 1;
    if (a < b) return -1;
    return 0;
}

..because else is unnecessary after a return; and because "if without braces followed by statement on its own line" creates a risk of someone accidentally inserting a new line without realizing it and breaking everything (for an example, see https://dwheeler.com/essays/apple-goto-fail.html ).

Tags:

C