Finding number of bits in an integer type

Advertisements

I have written a program to find number of bits on a given machine.

#include <stdio.h>

int int_size(void);

int main(int argc, char *argv[])
{
    printf("%d\n", int_size());
    
 
    return 0;
}

int int_size(void)
{
    int count = 1;
    int value = 1;

    while (1)
    {   
        value <<= 1;
        if (value > 0)
        {
            count++;
        }
        else
        {
            break;
        }

    }

    return count + 1;
}

Now idea behind this is as follows. On most of the systems, left most bit is 1 for negative numbers. So, I start with 1. If the system used 8 bits for storing an integer, then 1 would be represented as 0000 0001. I then go on left shifting this number and then check whether its positive. Now, when number becomes, 1000 0000, left most bit is 1 and this would be taken as a negative number on most systems. So, while loop is exited and I get the count for the bits. I have tried this program on 7 online C compilers and all return value 32. So an integer has 32 bits on these systems. Now, I still don’t know if my code is portable enough. Are there any machines that do not have left most bit as 1 for negative numbers ? I have come across three methods to store negative number. two’s complement, one’s complement and sign + magnitude. All three have left most bit 1 for negative numbers. So, this method should work on all systems.

>Solution :

Now, I still don’t know if my code is portable enough.

Your code has undefined behavior so the answer is: No

From C (draft) standard N1570:

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with
zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo
one more than the maximum value representable in the result type. If E1 has a signed
type and nonnegative value
, and E1 × 2E2 is representable in the result type, then that is
the resulting value; otherwise, the behavior is undefined.

When your value is at 230 and you do one more left shift, the result is 231 which isn’t representable in an int. Therefore you end in the "otherwise, the behavior is undefined" part.

If you don’t want to use sizeof then you can write a program using unsigned types and test for zero for detecting the overflow. You actually already do that so all you need is unsigned int value = 1; and you are safe.

That will work because the standard says:

For each of the signed integer types, there is a corresponding (but different) unsigned
integer type (designated with the keyword unsigned) that uses the same amount of
storage (including sign information) …

Leave a ReplyCancel reply