Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculating Ranges of Data Types in C

Tags:

c

I'm working through K&R Second Edition, and can't figure out why I'm getting a certain result. The problem I'm solving is calculating upper and lower limits for data types. Specifically:

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

I've learned about bitwise operators and two's compliment, and have a solution I think should work for signed data types, but instead it's working for unsigned data types which doesn't make any sense to me. Here's the code:

#include <stdio.h>

main()
{
    signed int i;

    i = ~0;
    i >>= 1;
    printf("Upper limit: %d\n", i);
    printf("Lower limit: %d\n", -i -1);
}

This will result in -1 being printed for the upper limit, and 0 printed for the lower limit. However, if I change i to an unsigned int, I get the result I was expecting (2147483647 and -2147483648). I can't wrap my head around this, because my understanding is that an unsigned int can never be less than 0, and a signed int should work using these bitwise operators, ie, if it's a 32 bit system,

~0 == 11111111111111111111111111111111

, and

~0 >> 1 == 011111111111111111111111111111111, 
           or 2147483647.

Any idea where I'm going wrong?

like image 910
jsutterfield Avatar asked Jul 22 '13 19:07

jsutterfield


People also ask

How do I find the range of data types in C?

Write a C program to find the range of data types using the c library and without it. In this programming language, all the range information, such as the minimum and maximum constants, will be within the limits and float header files. The limits.h header file has information about integers and characters.

How many data types are there in C?

Data Types in C Data Type Memory (bytes) Range Format Specifier short int 2 -32,768 to 32,767 %hd unsigned short int 2 0 to 65,535 %hu unsigned int 4 0 to 4,294,967,295 %u int 4 -2,147,483,648 to 2,147,483,647 %d 9 more rows ...

How to find the size of data types in C language?

The range of data types can be found by manually or using <limits.h> and <float.h> The size of data types in C is dependent on the compiler or you can say that the system architecture i.e. 32-bit compiler or 64-bit compiler. The size of data type int is 2 byte in 32-bit architecture or 4 bytes in 64-bit architecture.

How to print range data type like INT in C++?

C++ program for printing the range data type like int, char, short. METHOD 1.) calculate total number of bits by multiplying sizeof with 8 (say n) 2.) Calculate -2^ (n-1) for minimum range 3.) Calculate (2^ (n-1))-1 for maximum range


3 Answers

by using %d you treat your value as signed to proceed by printf.

you may use %u instead.

added

As Magn3s1um pointed out you don't need to specify signed and unsigned for your particular task printf will make all job for you.

like image 54
triclosan Avatar answered Oct 10 '22 12:10

triclosan


Output:

  1. Note:
    “In the expression i >>= 1, a negative value is shifted right. The C standard says this is an implementation-defined operation, and many implementations define it to be arithmetic shift. In an arithmetic shift, the most significant bit is unchanged (keeps MSB (signed bit) = 1)".

    (you can read: Right shifting negative numbers in C that >> is compiler dependent whether its singed or unsinfed shift, but probably in your case its doing an Arithmetic Shift.)

    For this reason after code:

     i = ~0;  
     i >>= 1;
    

    i remains ~0. that is in binary == 11111111111111111111111111111111.

    And because ~0 == 11111111111111111111111111111111 is == 2'c complement of 1 that is -1.

    So when you prints with format string %d it print -1. You should use %u to print max unsigned value that is == ~0.

    Important to note here:

    §6.2.6.2 Language 45, ©ISO/IEC ISO/IEC 9899:201x

    (ones’ complement). Which of these applies is implementation-defined, as is whether the value with sign bit 1 and all value bits zero (for the first two), or with sign bit and all value bits 1 (for ones’ complement), is a trap representation or a normal value. In the case of sign and magnitude and ones’ complement, if this representation is a normal value it is called a negative zero.

    Your understanding that :

    ~0 >> 1 == 011111111111111111111111111111111 is wrong! (it may be but not happening in your system, according to output)

    ~0 >> 1 == 111111111111111111111111111111111, note MSB(signed bit) is 1.

    For unsigned shift, try following:

    ~0U >> 1 == 011111111111111111111111111111111

    Notice Suffix U for unsigned.

  2. Second printf:
    Because i is -1, So in second expression -i - 1 == - (-1) - 1 == 1 - 1 == 0 so output is zero : 0.

like image 36
Grijesh Chauhan Avatar answered Oct 10 '22 10:10

Grijesh Chauhan


Your compiler implements >> as arithmetic shift. Therefore, the MSB keeps it value of 1 and the shift does nothing.

That is, ~0 >> 1 is still ~0 because the shift sign-extends.

See here: https://stackoverflow.com/a/7632/1974021

like image 3
DasKrümelmonster Avatar answered Oct 10 '22 12:10

DasKrümelmonster