C++: abs() and its quirk with INT_MIN

If you use the abs() function from cmath, then you need to be aware of one little quirk. The abs() function returns the absolute value of the signed integer passed as input. It is declared as:

int abs( int );

abs() works as defined for all input integers, except for one integer: the INT_MIN. For 32-bit integers, the value of INT_MIN is -2147483648. abs( INT_MIN ) returns INT_MIN back!

To see why, consider the binary representation of any signed integral type (char, short, int and long). The range of the positive integer values that can be represented is one less than that of negative integer values.

For 32-bit integers, the largest representable integer (INT_MAX) is 2147483647, whereas the smallest representable integer (INT_MIN) is not -2147483647, but it is -2147483648. Though the number of values that can be represented by an integral type is even, integer value 0 steals one space and thus the positive integer values lose one space in their range.

Coming back to abs(), since its return type is the same as the input type it simply cannot represent the positive value (-INT_MIN) in an int. Thus, it returns back INT_MIN.

The binary representation of 0 is 00000000000000000000000000000000 and the binary representation of INT_MIN is 10000000000000000000000000000000. That is, INT_MIN is same as 0, with MSB set to 1. Quirks of integers, such as with abs(), could have been avoided if the int format had been defined with two zero values: a positive zero (00000000000000000000000000000000) and a negative zero (10000000000000000000000000000000).

Anyway, the reason you need to be careful about abs() is because you might be using its return value to index into an array. Indexing an array using a negative value can be disastrous or result in a hard-to-replicate bug.

About these ads