Search code examples
ccastingcomparisonunsignedsigned

C: performing signed comparison in unsigned variables without casting


i want a function with the following signature:

bool signed_a_greater_than_signed_b(unsigned char a, unsigned char b);

its output should be 1 iff the 2's-complement view of the bits stored in a is greater than the 2's complement view of the bits stored in b. otherwise the output should be 0. for example:

signed_a_greater_than_signed_b(0b10000000,any number) => 0
signed_a_greater_than_signed_b(0b01111111,any number other than 0b01111111) => 1
signed_a_greater_than_signed_b(0b00000000,0b00000001) => 0
signed_a_greater_than_signed_b(0b00000000,0b11111111) => 1
signed_a_greater_than_signed_b(0b00000000,0b00000000) => 0

the function is not to have any implicit/explicit conversions (as these conversions are implementation-defined, and thus not portable)

one such implementation is:

bool signed_a_greater_than_signed_b(unsigned char a, unsigned char b)
{
    // if 'signed' a is positive then 
    //     return 1 if a is greater than b or b is negative
    // otherwise, if 'signed' a is negative then 
    //     return 1 if a is greater than b and b is negative
    if (a <= 0b01111111) return ((b < a) || (b > 0x01111111));
    else                 return ((b < a) && (b > 0x01111111));
}

can you suggest an implementation that uses arithmetic rather than conditionals to perform this calculations? you may use one condition if you must

using a mix of un/signed variables in comparisons and arithmetic in C is a recipe for disaster. this function is an example of how to circumvent the problem.

i guess the assembly behind comparison of signed variables is similar to the function i want to implement (on architectures not supporting signed comparisons)


Solution

  • Assuming 2's complement:

    return (a^signbit) > (b^signbit);
    

    where signbit is obviously the MSB of the representation.