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

1. ## 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. 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. 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.

4. Originally Posted by trievideo
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.

5. Thanks for the responses, but I'm a bit confused. As a noob, I don't know how to:
Originally Posted by Salem
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. 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.

7. 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. Originally Posted by itCbitC
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.

9. Originally Posted by grumpy
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.
Originally Posted by grumpy
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. 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. Originally Posted by cas
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.
Originally Posted by cas
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.
Originally Posted by cas
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. Originally Posted by itCbitC
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. Originally Posted by anduril462
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.
Originally Posted by anduril462
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. 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.

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)
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. Originally Posted by anduril462
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.
Originally Posted by anduril462
The standard does say anything goes.
The reason that the std. leaves it undefined, because it is hardware dependent.
Originally Posted by anduril462
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