This month’s Exercise may not have been challenging. Still, remember that blog is about learning the C language. Sometimes performing what could be a simple task may end up being complex than you anticipated.
Sadly, this challenge probably wasn’t that complex. Still, it opens an insight into a programming quirk you may not have expected. Before revealing the quirk, here is my solution:
2024_04-Exercise.c
#include <stdio.h> int main() { int a; printf("Enter an integer: "); scanf("%d",&a); if( a<0 ) a = -a; printf("The absolute value is %d\n",a); return 0; }
The code prompts for an integer value, int a
. If the value is less than zero — meaning that it’s negative — the negation operator flips the value positive: a = -a
. This expression isn’t the same as a -= a
, which would always be zero. No, it negates the negative, turning it positive. The result is output.
Here’s a sample run:
Enter an integer: -200
The absolute value is 200
And now for the quirk:
Enter an integer: -2147483648
The absolute value is -2147483648
When a negative value is input at the bottom of the signed integer’s range, the result is the same negative value.
The range for a 32-bit signed int data type in C is from -2,147,483,648 to 2,147,483,647. Due to the way negative values are expressed in binary, you cannot flip the lowest negative value to a positive as it would be out of range: The upper limit of an int data type is 2,147,483,647, not 2,147,483,648.
This effect holds for the C library’s abs() function as well: If you recode the solution to use abs() (which requires including the stdlib.h
header file), you get the same results.
Here’s the nerdy part: When incremented, the 32-bit value 2,147,483,647 becomes -2,147,483,648. Therefore, the absolute value of -2,147,483,648 cannot be calculated as it’s beyond the range of a signed 32-bit integer.
I hope you enjoyed the challenge and their weird aspect of finding the absolute value of an integer’s negative minimum.
IMHO abs() should throw an error when passed the argument -2147483648 and not doing so is a bug.
I think setting
errno
toERANGE
would be the most consistent way to go about this—thereʼs even a nice precedent in that functions likestrtol()
also set an error code ofERANGE
if the passed argument should be too large for successful conversion.