Thread: Random response when int value goes over 2,147,483,647..

  1. #1
    Registered User
    Join Date
    Jan 2011
    Posts
    11

    Random response when int value goes over 2,147,483,647..

    On my machine signed ints have a maximum value of 2,147,483,647. I've written a program that's designed to tell the user when the input value is too high. I have an error message (using printf) saying, "Error: Integer exceeds the 2,147,483,647 limit!" The problem is the program doesn't print the error message. Instead, it responds with apparently random output to terminal (whenever the int limit of 2,147,483,647 is exceeded).

    Here's the offending code:
    Code:
    int number,RightDigit,TotalDigits,D1,D2,D3,D4,D5,D6,D7,D8,D9,D10;
        printf("Type in any number less than 2,147,483,648:");
    	scanf("%i",&number);
    	if (number<10)
    		TotalDigits=1;
    	else if (number<100)
    		TotalDigits=2;
    	else if (number<1000)
    		TotalDigits=3;
    	else if (number<10000)
    		TotalDigits=4;
    	else if (number<100000)
    		TotalDigits=5;
    	else if (number<1000000)
    		TotalDigits=6;
    	else if (number<10000000)
    		TotalDigits=7;
    	else if (number<100000000)
    		TotalDigits=8;
    	else if (number<1000000000)
    		TotalDigits=9;
    	else if (number<=2147483647)
    		TotalDigits=10;
    
    	else
    		printf("Error:Integer exceeds 2,147,483,647 limit!");
    Any ideas on how to get my program to print the error message?

  2. #2
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    If the value you entered is greater than the type maximum value.(INT_MAX in your case)
    the overflow is already been done at the point of input.

    It's like
    Code:
      int n = INT_MAX + 1;  // n is already overflown!
      if(n > INT_MAX) {  // pointless
    You could use any type that can hold bigger than int.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Yes, use a string for input and then use strtoul() to do the conversion.

    Then pay attention to the error results it can return.

    scanf() just silently ignores integer overflow.
    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.

  4. #4
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by trievideo View Post
    Any ideas on how to get my program to print the error message?
    Make number unsigned or change the test condition because any int > 2,147,483,647 becomes negative i.e. still < 2147483647.
    And make sure to enter the input w/o commas in them otherwise it'll confuse the heck out of scanf(), giving a bizarre result.
    Last edited by itCbitC; 01-27-2011 at 09:45 AM.

  5. #5
    Registered User
    Join Date
    Jan 2011
    Posts
    11
    Thanks for the responses, but I'm a bit confused. As a noob, I don't know how to:
    Quote Originally Posted by Salem View Post
    Use a string for input and then use strtoul() to do the conversion.

    Then pay attention to the error results it can return.
    Without using scanf(), how do you get input from the user to put into a string in strtoul()? How do you code that in a situation like mine?

    I googled and found this code snippet, but I don't know exactly how to write this code into my program:

    Code:
    #include <stdlib.h>
       ...
    char *s;
    unsigned long uli;
       ...
    s = "2147483647";
    uli = strtoul("2147483647",NULL,10);
    I don't want to change the int to another type. So, if it's possible to use strtoul() without changing my int variables to another type, how do I do it? If anyone can provide a code snippet that would work in my program, that would be great!

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Well you use fgets() to read a line of input as a string.

    Then you use strtoul() / strtol() to parse that, store the result in an (unsigned) long and check for overflow / underflow (and other errors).

    You then range-check the long variable to make sure it will fit in an int (use INT_MIN/MAX) and then assign to your int with a cast.
    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.

  7. #7
    Registered User
    Join Date
    Jan 2011
    Posts
    11
    Thanks for the quick response, Salem! I think I follow you 95%. It's going to take me a day or two to understand how to implement this in my code, but thanks for sending me in the right direction. Your suggestion sounds as if it's exactly what I'm looking for!

  8. #8
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by itCbitC View Post
    Make number unsigned or change the test condition because any int > 2,147,483,647 becomes negative i.e. still < 2147483647.
    Incorrect on two counts;

    1) Making a value unsigned is insufficient to detect overflow.

    2) Overflow of a signed integral type is not guaranteed to give a negative result. The result is formally undefined according to the standard (which means absolutely anything is allowed to happen). The "random result" suggested by the OP is one permitted result.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  9. #9
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by grumpy View Post
    Incorrect on two counts;

    1) Making a value unsigned is insufficient to detect overflow.
    Dang! I meant to say unsigned long long to have some cushion (bitwise speaking) to play with, tho' even that would fail if o/p types in a no. >= 2^64.
    Quote Originally Posted by grumpy View Post
    2) Overflow of a signed integral type is not guaranteed to give a negative result. The result is formally undefined according to the standard (which means absolutely anything is allowed to happen). The "random result" suggested by the OP is one permitted result.
    The std leaves it undefined as it's hardware dependent, tho' signed ints on 2's and 1's complement machines cross over to the other side if the MSB flips.

  10. #10
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    The std leaves it undefined as it's hardware dependent, tho' signed ints on 2's and 1's complement machines cross over to the other side if the MSB flips.
    It's true, of course, that with 2's complement you know what'll happen on overflow. However, since the standard leaves signed overflow undefined regardless of the hardware representation, compilers are free to assume no signed overflow will happen. This is not just theoretical, either. Gcc recently added an optimization that assumes signed overflow will not occur. Try the following code with a recent gcc (I'm using 4.5.2):
    Code:
    void f(void)
    {
      for(int i = 1; i > 0; i += i)
      {
      }
    }
    
    int main(void)
    {
      f();
    
      return 0;
    }
    With no optimization, this does what's expected: quits immediately (the loop runs 31 times, then overflows).

    However, try with -O2. The loop runs infinitely, since gcc “knows” i will always be greater than zero. This is a perfectly valid optimization, since the code is undefined.

  11. #11
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by cas View Post
    It's true, of course, that with 2's complement you know what'll happen on overflow. However, since the standard leaves signed overflow undefined regardless of the hardware representation, compilers are free to assume no signed overflow will happen.
    While that is true, the compiler has no magic 8 ball nor does it know the programmer's numerical intentions. So in the absence of such foresight it conforms to the low-level ABIs and the micro's architecture.
    Quote Originally Posted by cas View Post
    This is not just theoretical, either. Gcc recently added an optimization that assumes signed overflow will not occur. Try the following code with a recent gcc (I'm using 4.5.2):
    Code:
    void f(void)
    {
      for(int i = 1; i > 0; i += i)
      {
      }
    }
    
    int main(void)
    {
      f();
    
      return 0;
    }
    With no optimization, this does what's expected: quits immediately (the loop runs 31 times, then overflows).
    One would be wary of such a compiler as it implies that ints are only 6 bits wide.
    Quote Originally Posted by cas View Post
    However, try with -O2. The loop runs infinitely, since gcc “knows” i will always be greater than zero. This is a perfectly valid optimization, since the code is undefined.
    Does it run indefinitely or 2^31-1 times? Print the value of i when the for loop in f() ends.

  12. #12
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by itCbitC View Post
    One would be wary of such a compiler as it implies that ints are only 6 bits wide.
    I think you misread the loop same as I did. It's i += i, not i += 1. This doubles it each time, so 31 iterations is 32 bit, 1's or 2's compliment.

    Does it run indefinitely or 2^31-1 times? Print the value of i when the for loop in f() ends.
    Indefinitely. Here's the assembly (from gcc -S -Wall -O2 loop.c):
    Code:
    .globl f
        .type   f, @function
    f:
        pushl   %ebp
        movl    %esp, %ebp
    .L2:
        jmp .L2
        .size   f, .-f
        .p2align 4,,15
    Note the .L2 label with a loop body of only jmp .L2. No way to exit.

  13. #13
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by anduril462 View Post
    I think you misread the loop same as I did. It's i += i, not i += 1. This doubles it each time, so 31 iterations is 32 bit, 1's or 2's compliment.
    Ah! I see adding i to itself (i = i + i) not 1.
    IOW, multiply i by 2 or left shift i by one.
    Quote Originally Posted by anduril462 View Post
    Indefinitely. Here's the assembly (from gcc -S -Wall -O2 loop.c):
    Code:
    .globl f
        .type   f, @function
    f:
        pushl   %ebp
        movl    %esp, %ebp
    .L2:
        jmp .L2
        .size   f, .-f
        .p2align 4,,15
    Note the .L2 label with a loop body of only jmp .L2. No way to exit.
    Whoa! that makes no sense, imo.
    Only way it'd loop indefinitely would be if 1's were pushed in from the right hand side instead of zeros.
    Methinks! this is a serious bug with whatever version of the gcc compiler that both you and cas are using.
    What version of gcc do you have? Meantime I'll find a machine with gcc and I'll get back to you with my results.

  14. #14
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    My work computer produced the infinite loop, my box at home didn't, though my box at home has a 2.5 year old gcc. Not sure about the bug thing, I think cas is right on gcc making assumptions about signed overflow not going negative and the resultant infinite loops for optimizations. The standard does say anything goes.

    Quote Originally Posted by Work Computer
    $ cat /etc/redhat-release
    Fedora release 13 (Goddard)
    $ gcc --version
    gcc (GCC) 4.4.4 20100503 (Red Hat 4.4.4-2)
    Quote Originally Posted by Home Computer
    $ cat /etc/redhat-release
    CentOS release 5.5 (Final)
    $ gcc --version
    gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-48)
    Something changed in there, but I haven't made it through all the change logs and known bugs yet to see whether it was intentional (not the most exciting reading).

  15. #15
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by anduril462 View Post
    My work computer produced the infinite loop, my box at home didn't, though my box at home has a 2.5 year old gcc. Not sure about the bug thing, I think cas is right on gcc making assumptions about signed overflow not going negative and the resultant infinite loops for optimizations.
    Even if gcc is making an assumption about signed overflow not going negative, it doesn't mean that it is doin' it right. Let's say currently i == 0x80000000; next iteration i == 0x100000000 (value too big for an int); i gets the truncated value i.e. 0x00000000. This terminates the loop.
    Quote Originally Posted by anduril462 View Post
    The standard does say anything goes.
    The reason that the std. leaves it undefined, because it is hardware dependent.
    Quote Originally Posted by anduril462 View Post
    Something changed in there, but I haven't made it through all the change logs and known bugs yet to see whether it was intentional (not the most exciting reading).
    Or you could open a bug report and see if the gcc maintainers corroborate the results

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how to combine these working parts??
    By transgalactic2 in forum C Programming
    Replies: 0
    Last Post: 02-01-2009, 08:19 AM
  2. Code review
    By Elysia in forum C++ Programming
    Replies: 71
    Last Post: 05-13-2008, 09:42 PM
  3. Replies: 8
    Last Post: 03-10-2008, 11:57 AM
  4. Working with random like dice
    By SebastionV3 in forum C++ Programming
    Replies: 10
    Last Post: 05-26-2006, 09:16 PM
  5. How do you search & sort an array?
    By sketchit in forum C Programming
    Replies: 30
    Last Post: 11-03-2001, 05:26 PM