简体   繁体   中英

Finding maximum value of a short int variable in C

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.

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`.

Per definition, you cannot calculate the maximum value of a type in C, by using variables of that very same type. It simply doesn't make any sense. The type will overflow when it goes "over the top". In case of signed integer overflow, the behavior is undefined, meaning you will get a major bug if you attempt it.

The correct way to do this is to simply check SHRT_MAX from limits.h.

An alternative, somewhat more questionable way would be to create the maximum of an unsigned short and then divide that by 2. We can create the maximum by taking the bitwise inversion of the value 0.

#include <stdio.h>
#include <limits.h>

int main()
{ 
  printf("%hd\n", SHRT_MAX); // best way

  unsigned short ushort_max = ~0u;
  short short_max = ushort_max / 2;
  printf("%hd\n", short_max);

  return 0;
}

One note about your code:

Casts such as ((short int)2*i)>(short int)0 are completely superfluous. Most binary operators in C such as * and > implement something called "the usual arithmetic conversions", which is a way to implicitly convert and balance types of an expression. These implicit conversion rules will silently make both of the operands type int despite your casts.

You forgot to cast to short int during comparison

OK, here I assume that the computer would handle integer overflow behavior by changing into negative integers, as I believe that you have assumed in writing this program.

code that outputs 32767:

#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
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 ((short int)(i + j) <= (short int)0)
                j /= 2;
            i += j;
        }
    }

    return i;
}

int main() {
    printf("%d", max_short());
    while (1);
}

added 2 casts

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM