Manual calculation of variable type ranges

This is a discussion on Manual calculation of variable type ranges within the C Programming forums, part of the General Programming Boards category; Exercise 2-1: Write a program to determine the ranges of char, short, int, and long variables, both signed and unsigned, ...

  1. #1
    Registered User
    Join Date
    Feb 2010
    Posts
    31

    Manual calculation of variable type ranges

    Exercise 2-1: 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...

    I've worked out how to printf the values of the constants stored in <limits.h> and <float.h> but am not sure of a method to calculate the min/max values, for example, of a short int. My loop method seems to cause the function to stop responding:

    Code:
    #include <stdio.h>
    #include <limits.h>
    #include <float.h>
    
    int main()
    {
    printf("Maximum Int value: %d\n", SHRT_MAX);
    printf("Maximum Float value: %f", FLT_MAX);
    
    short c;
    
    for (c = 0; c < 999999; ++c) {}
    printf("\n\nValue of c is: %d", c);
    
        return 0;}
    Is there some kind of 'while c is under its limit' code I could insert into the area I've emboldened?
    Thanks

  2. #2
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,485
    Study the value of ~0 for various unsigned types.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  3. #3
    Registered User
    Join Date
    Feb 2010
    Posts
    31
    Thanks! I got this as an output:

    Value of 'a' is: -1
    Value of 'b' is: 65535
    Value of 'c' is: 255
    Value of 'd' is: -1.0000000

    from
    Code:
    #include <stdio.h>
    
    int main()
    {
        unsigned long a = ~0;
        unsigned short b = ~0;
        unsigned char c = ~0;
        float d = ~0;
    
        printf("Value of 'a' is: %d\nValue of 'b' is: %d\nValue of 'c' is: %d\nValue of 'd' is: %f", a, b,c,d);
    
    return 0;}
    I'm not sure what to infer from this as to how '~0' works. Perhaps upper limit?> but then why -1 for the long and float?

    Thanks

  4. #4
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,485
    You declare them as unsigned, then print them as signed.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  5. #5
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Kayl669 View Post
    I'm not sure what to infer from this as to how '~0' works.
    "The bitwise complement operator, the tilde, ~, flips every bit. A useful way to remember this is that the tilde is sometimes called a twiddle, and the bitwise complement twiddles every bit: if you have a 1, it's a 0, and if you have a 0, it's a 1."

    So, with an unsigned type, ~0 will be the highest possible number, because all bits are set.

    With a signed type, it will also be all bits set, (eg, a four byte int: 11111111 11111111 11111111 11111111). This is the opposite of 0, which is no bits set.

    However, signed types use the Most Significant Bit (that is, the one which would represent the highest value when unsigned) to indicate positive or negative, and negative numbers are represented using a system called two's complement:

    Two's complement - Wikipedia, the free encyclopedia

    A useful thing to understand altho it took me a while

    This is why:
    0111111 1111111 11111111 11111111 == highest positive signed value
    0000000 0000000 00000000 00000001 == 1
    0000000 0000000 00000000 00000000 == 0
    1111111 1111111 11111111 11111111 == -1.
    1000000 0000000 00000000 00000000 == lowest possible negative signed value

    That means the lowest possible neg signed value is -(highest possible value + 1).

    Floats involve addition complications.
    Last edited by MK27; 02-22-2010 at 09:14 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  6. #6
    Registered User
    Join Date
    Feb 2010
    Posts
    31
    Thanks for your help both. Can I confirm with you that in a printf context %d is used for signed ints and %u for unsigned ints... What about unsigned chars too?

    MK, I kinda get Two's complement for signed variables, although how do I find my min/max values without starting with 0 or -1 and somehow changing the MSB?

    Thanks

  7. #7
    Registered User
    Join Date
    Feb 2010
    Posts
    31
    Actually I spose you wouldn't use char variables in a printf context...that's more putchar()

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,598
    Quote Originally Posted by Kayl669
    Can I confirm with you that in a printf context %d is used for signed ints and %u for unsigned ints... What about unsigned chars too?
    You can print an unsigned char with %u as well since its value will not change.

    Quote Originally Posted by Kayl669
    I kinda get Two's complement for signed variables, although how do I find my min/max values without starting with 0 or -1 and somehow changing the MSB?
    I think that this depends on what assumptions you want to make. If you assume that the signed integer representation is two's complement, then you can work out the range just by using sizeof and CHAR_BIT.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Feb 2010
    Posts
    31
    Thanks laserlight. Although can you give me an example as I'm not very knowledgeable about in-built functionality. Also I think CHAR_BIT is part of the limits header and my exercise tells me I should be able to both calculate the range of different variable types aswell as using <limits.h>.

    Thanks again

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,598
    Quote Originally Posted by Kayl669
    Although can you give me an example as I'm not very knowledgeable about in-built functionality.
    I was thinking of something like this:
    Code:
    #include <stddef.h>
    #include <limits.h>
    #include <stdio.h>
    
    int main(void)
    {
        /* Assume two's complement. */
        int int_max = (int)((1U << (sizeof(int) * CHAR_BIT - 1)) - 1);
        printf("Maximum value of int: %u\n", int_max);
        printf("Minimum value for int: %d\n", -int_max - 1);
        return 0;
    }
    Quote Originally Posted by Kayl669
    Also I think CHAR_BIT is part of the limits header and my exercise tells me I should be able to both calculate the range of different variable types aswell as using <limits.h>.
    You do not need CHAR_BIT if you can validly assume that there are 8 bits in a byte. The problem is, if you assume nothing, i.e., you do not know if two's complement is used (but you know that it might be one's complement or sign and magnitude instead), you do not know how many bits there are in a byte (other than a minimum of 8), and you cannot refer to anything in <limits.h>, then it might be impossible to determine the maximum and minimum values of a signed integer type without risking undefined behaviour (and possibly getting a wrong answer).

    EDIT:
    It looks like this macro works:
    Code:
    #include <stdio.h>
    
    #define BITS_PER_BYTE 8 /* Assumption without CHAR_BIT. */
    
    /* Assume two's complement. */
    #define PRINT_RANGE(integer_type) do {\
        integer_type num_max = (integer_type)((1UL << (sizeof(integer_type) * BITS_PER_BYTE - 1)) - 1);\
        printf("Maximum value of " #integer_type ": %lu\n", (unsigned long)num_max);\
        printf("Minimum value of " #integer_type ": %ld\n", (long)(-num_max - 1));\
    } while (0)
    
    int main(void)
    {
        PRINT_RANGE(signed char);
        PRINT_RANGE(short);
        PRINT_RANGE(int);
        PRINT_RANGE(long);
        return 0;
    }
    But it basically just boils down to finding the number of bits of the type, and then computing the maximum/minimum values with that information.
    Last edited by laserlight; 02-22-2010 at 01:03 PM.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Feb 2010
    Posts
    31
    Ok I've got a lot of new stuff to learn here! Thanks for your help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. LDAP Query
    By Travoiz in forum C++ Programming
    Replies: 0
    Last Post: 08-13-2009, 02:58 PM
  2. sorting number
    By Leslie in forum C Programming
    Replies: 8
    Last Post: 05-20-2009, 04:23 AM
  3. Need some help...
    By darkconvoy in forum C Programming
    Replies: 32
    Last Post: 04-29-2008, 03:33 PM
  4. gcc problem
    By bjdea1 in forum Linux Programming
    Replies: 13
    Last Post: 04-29-2002, 06:51 PM
  5. Variable Allocation in a simple operating system
    By awkeller in forum C Programming
    Replies: 1
    Last Post: 12-08-2001, 01:26 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21