Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why int i=400*400/400 gives result 72, is datatype circular?

Tags:

c++

c

types

I think first 400*400=160000 is converted to 28928 by starting from 0 and going 160000 time in a circular fashion for int type (say sizeof(int) = 2 bytes) assuming it like:

enter image description here

And then 28928 is divided by 400, floor of which gives 72 and the result varies with the type of variable. Is my assumption correct or there is any other explanation?

like image 287
Imran Rana Avatar asked Jan 29 '12 09:01

Imran Rana


2 Answers

Assuming you're using a horrifically old enough compiler for where int is only 16 bits. Then yes, your analysis is correct.*

400 * 400 = 160000 

//  Integer overflow wrap-around.
160000 % 2^16 = 28928

//  Integer Division
28928 / 400 = 72 (rounded down)

Of course, for larger datatypes, this overflow won't happen so you'll get back 400.

*This wrap-around behavior is guaranteed only for unsigned integer types. For signed integers, it is technically undefined behavior in C and C++.

In many cases, signed integers will still exhibit the same wrap-around behavior. But you just can't count on it. (So your example with a signed 16-bit integer isn't guaranteed to hold.)


Although rare, here are some examples of where signed integer overflow does not wrap around as expected:

  • Why does integer overflow on x86 with GCC cause an infinite loop?
  • Compiler optimization causing program to run slower
like image 96
Mysticial Avatar answered Sep 26 '22 18:09

Mysticial


It certainly seems like you guessed correctly.

If int is a 16-bit type, then it'll behave exactly as you described. Your operation happens sequentially and 400 * 400 produces 160000, which is 10 0111 0001 0000 0000

when you store this in 16-bit register, top "10" will get chopped off and you end up with 0111 0001 0000 0000 (28,928).... and you guessed the rest.

Which compiler/platform are you building this on? Typical desktop would be at least 32-bit so you wouldn't see this issue.

UPDATE #1

NOTE: This is what explain your behavior with YOUR specific compiler. As so many others were quick to point out, DO NOT take this answer to assume all compilers behave this way. But YOUR specific one certainly does.

To complete the answer from the comments below, the reason you are seeing this behavior is that most major compilers optimize for speed in these cases and do not add safety checks after simple arithmetic operations. So as I outlined above, the hardware simply doesn't have room to store those extra bits and that's why you are seeing "circular" behavior.

like image 36
DXM Avatar answered Sep 24 '22 18:09

DXM