Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to programmatically determine maximum and minimum limit of int data in C?

Tags:

c

I am attempting exercise 2.1 of K&R. The exercise reads:

Write a program to determine the ranges of char, short, int, and long variables, both signed and unsigned, by printing appropriate values from standard headers and by direct computation. Harder if you compute them: determine the ranges of the various floating-point types.

Printing the values of constants in the standards headers is easy, just like this (only integer shown for example):

printf("Integral Ranges (from constants)\n");
printf("int max: %d\n", INT_MAX);
printf("int min: %d\n", INT_MIN);
printf("unsigned int max: %u\n", UINT_MAX);

However, I want to determine the limits programmatically.

I tried this code which seems like it should work but it actually goes into an infinite loop and gets stuck there:

printf("Integral Ranges (determined programmatically)\n");

int i_max = 0;

while ((i_max + 1) > i_max) {
        ++i_max;
}

printf("int max: %d\n", i_max);

Why is this getting stuck in a loop? It would seem that when an integer overflows it jumps from 2147483647 to -2147483648. The incremented value is obviously smaller than the previous value so the loop should end, but it doesn't.

like image 368
Sam Avatar asked Aug 08 '15 19:08

Sam


People also ask

How do you find the int data min and max values?

int min = (pow(2, number of bits assigned to data types) / 2) * -1; int max = (pow(2, number of bits assigned to data types) / 2) — 1; Let's use the unsigned short int data type with a max range of 65,535 . We can find it two ways.

Which are the minimum and maximum integers that can be stored in a C language variable of type int 32 bit wide )?

Values of INT_MAX and INT_MIN may vary from compiler to compiler. Following are typical values in a compiler where integers are stored using 32 bits. Value of INT_MAX is +2147483647. Value of INT_MIN is -2147483648.

What is INT_MIN and INT_MAX in C?

INT_MAX is a macro which represents the maximum integer value. Similarly, INT_MIN represents the minimum integer value. These macros are defined in the header file <limits.


2 Answers

Ok, I was about to write a comment but it got too long...

Are you allowed to use sizeof?

If true, then there is an easy way to find the max value for any type:

For example, I'll find the maximum value for an integer:

Definition: INT_MAX = (1 << 31) - 1 for 32-bit integer (2^31 - 1)

The previous definition overflows if we use integers to compute int max, so, it has to be adapted properly:

INT_MAX = (1 << 31) - 1
        = ((1 << 30) * 2) - 1
        = ((1 << 30) - 1) * 2 + 2) - 1
        = ((1 << 30) - 1) * 2) + 1

And using sizeof:

INT_MAX = ((1 << (sizeof(int)*8 - 2) - 1) * 2) + 1

You can do the same for any signed/unsigned type by just reading the rules for each type.

like image 170
JuanR Avatar answered Oct 18 '22 12:10

JuanR


So it actually wasn't getting stuck in an infinite loop. C code is usually so fast that I assume it's broken if it doesn't complete immediately.

It did eventually return the correct answer after I let it run for about 10 seconds. Turns out that 2,147,483,647 increments takes quite a few cycles to complete.

I should also note that I compiled with cc -O0 to disable optimizations, so this wasn't the problem.

A faster solution might look something like this:

int i_max = 0;
int step_size = 256;

while ((i_max + step_size) > i_max) {
    i_max += step_size;
}

while ((i_max + 1) > i_max) {
    ++i_max;
}

printf("int max: %d\n", i_max);

However, as signed overflow is undefined behavior, probably it is a terrible idea to ever try to programmatically guess this in practice. Better to use INT_MAX.

like image 33
Sam Avatar answered Oct 18 '22 13:10

Sam