Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding maximum value of a short int variable in C

Tags:

I was working on Exercise 2-1 of K&R, the goal is to calculate the range of different variable types, bellow is my function to calculate the maximum value a short int can contain:

short int max_short(void) {
    short int i = 1, j = 0, k = 0;
    while (i > k) {
        k = i;
        if (((short int)2 * i) > (short int)0)
            i *= 2;
        else {
            j = i;
            while (i + j <= (short int)0)
                j /= 2;
            i += j;
        }
    }
    return i;
}

My problem is that the returned value by this function is: -32768 which is obviously wrong since I'm expecting a positive value. I can't figure out where the problem is, I used the same function (with changes in the variables types) to calculate the maximum value an int can contain and it worked...

I though the problem could be caused by comparison inside the if and while statements, hence the typecasting but that didn't help...

Any ideas what is causing this ? Thanks in advance!

EDIT: Thanks to Antti Haapala for his explanations, the overflow to the sign bit results in undefined behavior NOT in negative values.

like image 206
ColdCoffeeMug Avatar asked Aug 25 '17 13:08

ColdCoffeeMug


1 Answers

You can't use calculations like this to deduce the range of signed integers, because signed integer overflow has undefined behaviour, and narrowing conversion at best results in an implementation-defined value, or a signal being raised. The proper solution is to just use SHRT_MAX, INT_MAX ... of <limits.h>. Deducing the maximum value of signed integers via arithmetic is a trick question in standardized C language, and has been so ever since the first standard was published in 1989.

Note that the original edition of K&R predates the standardization of C by 11 years, and even the 2nd one - the "ANSI-C" version predates the finalized standard and differs from it somewhat - they were written for a language that wasn't almost, but not quite, entirely unlike the C language of this day.

You can do it easily for unsigned integers though:

unsigned int i = -1;
// i now holds the maximum value of `unsigned int`.
like image 151