0

Help me to understand INTEGER OVERFLOW and working with INTEGER LIMITS in context of the following example.

I am unable to interpret the output of the following code.

I have considered three cases, directly printing , integers and unsigned long long integer.

#include<iostream>
#include<limits.h>
using namespace std;

int main()
{
int tmp1=0,tmp2=0,tmp3=0,tmp4=0;
unsigned long long temp1=0,temp2=0,temp3=0,temp4=0;

cout<<"Directly printing"<<endl;

cout<<-2*INT_MIN<<endl<<2*INT_MIN<<endl<<-2*INT_MAX<<endl<<2*INT_MAX<<endl;

cout<<"Using integer"<<endl;

tmp1 = -2*INT_MIN;
tmp2 = 2*INT_MIN;
tmp3 = -2*INT_MAX;
tmp4 = 2*INT_MAX;

cout<<temp1<<endl<<tmp2<<endl<<tmp3<<endl<<tmp4<<endl;

cout<<"Using unsigned long long variables"<<endl;

temp1 = -2*INT_MIN;
temp2 = 2*INT_MIN;
temp3 = -2*INT_MAX;
temp4 = 2*INT_MAX;

cout<<temp1<<endl<<temp2<<endl<<temp3<<endl<<temp4;
}

Output:

Directly printing
0
0
2
-2
Using integer
0
0
2
-2
Using unsigned long long variables
0
0
2
18446744073709551614
4
  • 1
    <limits.h> is the C header, not that it matters, but you might want to take a look at <limits> that has e.g. std::numeric_limits<int>::max() Commented Apr 14, 2016 at 9:11
  • 1
    You have undefined behavior in your code, you use the unsigned long long variables before they are initialized. In the "Using integer" section you print the values of temp1 etc., when you should be using tmp1 etc. Try to use better variable-naming and these things hopefully won't happen that much. Also, a good compiler would have issued warnings about this. Commented Apr 14, 2016 at 9:12
  • Sounds a lot like "do my homework for me". What relevant facts have you found so far? What specifically don't you understand? Is there anything specifically in the output that strikes you as unexpected? Draft C++ Standards papers are easily available online - did you try to understand anything about the limits or behaviours during overflow? Even if that's too daunting, specific questions can be researched on S.O.. Commented Apr 14, 2016 at 9:14
  • I am unable to understand the output. If you have some reference to C++ standard papers kindly share them Commented Apr 14, 2016 at 9:23

2 Answers 2

1

tmp1 = -2*INT_MIN; undefined behaviour unless INT_MAX has twice the magnitude of INT_MIN (it won't).

tmp2 = 2*INT_MIN; undefined behaviour (overflowing a signed integer)

tmp3 = -2*INT_MAX; undefined behaviour unless INT_MIN has twice the magnitude of INT_MAX (it won't).

tmp4 = 2*INT_MAX; undefined behaviour (overflowing a signed integer)

temp1 = -2*INT_MIN; undefined behaviour (overflowing a signed integer)

temp2 = 2*INT_MIN; undefined behaviour (overflowing a signed integer)

temp3 = -2*INT_MAX; undefined behaviour (overflowing a signed integer)

temp4 = 2*INT_MAX; undefined behaviour (overflowing a signed integer)

Sign up to request clarification or add additional context in comments.

4 Comments

"signed arithmetic with unsigned type" is simply promotion of signed value to unsigned is it not? And isn't that well defined ([conv.integral] )?
@user2079303 you're right. gcc is giving me "25 : warning: integer overflow in expression [-Woverflow]" for that line.
Indeed, those lines have the same undefined behaviour of overflowing the signed integer in the multiplication, as the lines above. INT_MAX and 2 are both signed.
I think the last bit is a bit redundant. All of the signed multiplications overflow (except -2*INT_MAX in the non-existing corner case) and have UB. All the assignments to unsigned would be well defined, whether the signed integer is in a representable range or not.
1

Introduction

So, an integer overflow is a computing error where, when a number gets too large (mainly >9223372036854775807; it could be >2147483647 that causes a problem), it will try to roll over.

Why doesn’t it go on forever?

Computers count in binary. In computer software, usually an Integer function will have 64 bits, although some (like Minecraft) only have 32.

I’ve heard of computers going to 18.446 quintillion!

That’s because those integers are unsigned. Most integers are signed.

How does the actual overflow happen?

So, as we know, computers count in binary. In signed processes, it goes up to 9223372036854775807, or more rarely, 2147483647. Since you are a novice, I won’t scare you with 64 bits. Here’s how it happens:

0000 0000 0000 0000 0000 0000 0000 0000 is 0
0000 0000 0000 0000 0000 0000 0000 0001 is 1
0000 0000 0000 0000 0000 0000 0000 0010 is 2

0111 1111 1111 1111 1111 1111 1111 1101 is 2147483645
0111 1111 1111 1111 1111 1111 1111 1110 is 2147483646
0111 1111 1111 1111 1111 1111 1111 1111 is 2147483647
1000 0000 0000 0000 0000 0000 0000 0000 is -2147483648!?

It went negative because in a signed process, the first bit (the 1 in 1000 0000 0000 0000 …) determines the sign. A 0 means + and a 1 means -.

What about my case?

Your case:

#include<iostream>
#include<limits.h>
using namespace std;

int main()
{
    int tmp1=0,tmp2=0,tmp3=0,tmp4=0;
    unsigned long long temp1=0,temp2=0,temp3=0,temp4=0;

cout<<"Directly printing"<<endl;

cout<<-2*INT_MIN<<endl<<2*INT_MIN<<endl<<-2*INT_MAX<<endl<<2*INT_MAX<<endl;

cout<<"Using integer"<<endl;

tmp1 = -2*INT_MIN;
tmp2 = 2*INT_MIN;
tmp3 = -2*INT_MAX;
tmp4 = 2*INT_MAX;

cout<<temp1<<endl<<tmp2<<endl<<tmp3<<endl<<tmp4<<endl;

cout<<"Using unsigned long long variables"<<endl;

temp1 = -2*INT_MIN;
temp2 = 2*INT_MIN;
temp3 = -2*INT_MAX;
temp4 = 2*INT_MAX;

cout<<temp1<<endl<<temp2<<endl<<temp3<<endl<<temp4;
}

This is wrong as multiplying an INT_MIN or INT_MAX by a number not -1, 0 or 1 will result in an Overflow. You are trying to multiply INT_MIN and INT_MAX by 2 and -2. Please remember that INT_MIN is the minimum, you can’t go below it and INT_MAX is the maximum, you can’t go above it.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.