-3

I've seen lots of places say:

In Turbo c and 16-bit range of Integer is -32768 to 32767 (0 to 65535) but in 32-bit and 64-bit range of Integer is -2147483648 [minimum value -2^31] to 2147483647 [maximum value 2^31-1]. But when we code and try to overflow the integer range like x=2147483649 c compiler returned x=-2147483647.

When we give (+ve) overflow value in x variable it returns (-ve) value or vise versa. And when we enter (+/-ve)2147483648 it always give (-ve) 2147483648 WHY ??

Example Code for better explanation

#include<stdio.h>

int main(){

    int x;

    x=2147483649;

    printf("%d",x);
    
    // if we give x=2147483649
    // Output will be -2147483647

    // if we give x=-2147483649
    // output will be +2147483647

    // if we give x=(+/-)2147483648
    // output will ve always -ve 2147483648

    return 0;

}
Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
  • C++ Signed overflow is Undefined Behaviour. See __Integer types__ in https://en.cppreference.com/w/cpp/language/types – Richard Critten May 31 '21 at 18:10
  • Why do you think 32-bit integers and 64-bit integers are the same size? – Joseph Sible-Reinstate Monica May 31 '21 at 18:10
  • 2
    `2147483648` isn't a valid 32-bit signed int value, so negating it is undefined. Compilers don't usually do *crazy* things though, they do something that is reasonable even if the C standard has not defined what should happen. – Weather Vane May 31 '21 at 18:10
  • 1
    What is your question? – Alan Birtles May 31 '21 at 18:17
  • Your last commented out example seems related to the classic [value of `abs(INT_MIN)`](https://stackoverflow.com/q/22268815/10871073). – Adrian Mole May 31 '21 at 18:20
  • 2s complement representation is usually used for signed integer types. This should explain observed effects for the overflow – fabian May 31 '21 at 18:24
  • @JosephSible-ReinstateMonica: OP is using “64-bit integer” to refer to an `int` type in a C implementation for a “64-bit” platform. – Eric Postpischil May 31 '21 at 18:33
  • @EricPostpischil That's... non-standard use of the term. – Joseph Sible-Reinstate Monica May 31 '21 at 18:35
  • @JosephSible-ReinstateMonica: Humans are not bound to conform to standards documents for natural language. – Eric Postpischil May 31 '21 at 18:36
  • @RichardCritten: There is no overflow here, and there is no undefined behavior here. Overflow occurs when the result of an operation is not representable in the operation’s result type. Assignment converts to the type of the left operand, and the result of the conversion is defined to be some value representable in the type. (In this case, it is implementation-defined.) – Eric Postpischil May 31 '21 at 18:38
  • Turbo C is what, 40 years old now? I don't think any modern implementations of C or C++ use 16 bit `int`, unless they're for some embedded processor. – Mark Ransom May 31 '21 at 19:01

2 Answers2

0

In an assignment such as x = 2147483649, the value on the right is converted to the type of the left operand. When converting to a signed integer type, if the source value cannot be represented in the destination type, the result of the conversion is defined by the implementation (largely by the compiler), per C 2018 6.3.1.3 3.

GCC defines the conversion to wrap modulo 2N, where N is the number of bits in the type1, and this is a common behavior among compilers.

Wrapping 2,147,483,649 modulo 232 produces 2,147,483,649 − 4,294,967,296 = −2,147,483,647.

This is not an overflow. Overflow, or, more generally, an exceptional condition, occurs when the result of an operation is not representable in the result type of the operation (C 2018 6.5 5). Since the conversion is defined to produce a result that is representable, no overflow occurs.

Footnote

1 The number of value bits and the sign bit, so 32 in this case. Padding bits are not included.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • @AnujBagdi: No, the reduction is performed modulo 2^32. The interval [−2,147,483,648, +2,147,483,647] contains 4,294,967,296 = 2^32 integers; it forms a cycle of length 2^32. And the arithmetic 2,147,483,649 − 4,294,967,296 = −2,147,483,647 shows the reduction is performed by subtracting 2^32. Subtracting 2^31 would produce 2,147,483,649 − 2,147,483,648 = 1, which is not the result you got. – Eric Postpischil Jun 01 '21 at 11:44
  • Okay, but I think 2147483649 modulo 2^31 is correct in place of 2^32. Now my question is when we enter a negative value it returns a positive value according to your **wrapping statement** but when we give a negative value like -2147483649 to an integer it returns a positive value +2147483647 why not it returns -2147483647 – Anuj Bagdi Jun 01 '21 at 11:50
  • @AnujBagdi: The GCC documentation I linked to in the question says the wrapping is modulo 2^N, where N is the width of the type. Per C 2018 6.2.6.2 6, the width of an integer type is the number of value bits and sign bit in it. For a 32-bit `int`, its width is 32, so the reduction is modulo 2^32. Further, I showed how the math does work when the reduction is modulo 2^32 and how it does not work when it is modulo 2^31. 2^31 is wrong. 2^32 is correct. – Eric Postpischil Jun 01 '21 at 23:36
  • @AnujBagdi: Two numbers are congruent modulo m iff their difference is an integer multiple of m. Every integer is congruent modulo 2^32 to exactly one integer in [−2,147,483,648, +2,147,483,647]. This follows from the [division theorem](https://en.wikipedia.org/wiki/Euclidean_division). Given any value x to be reduced modulo 2^32 to an integer in that interval, one adds or subtracts 2^32 until a number in that interval is reached. Given −2,147,483,649, to reduce it to a number in that interval, we must add, so we add 2^32: −2,147,483,649 + 4,294,967,296 = +2,147,483,647. – Eric Postpischil Jun 01 '21 at 23:40
-1

It helps if you look at the bit patterns of all those numbers. 32 bits is 8 hex digits, anything longer than that gets truncated on the left:

               32 bit       64 bit
2147483649:  0x80000001  0x0000000080000001
-2147483647: 0x80000001  0xffffffff80000001
-2147483649: 0x7fffffff  0xffffffff7fffffff
2147483647:  0x7fffffff  0x000000007fffffff
2147483648:  0x80000000  0x0000000080000000
-2147483648: 0x80000000  0xffffffff80000000
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622