Programmer
Programmer

Reputation: 8727

Integer overflow not occuring : they restart from 0

I tried a simple code and found that integers variables are not overflowing instead it seems that latest C++ compiler has introduced a new functionality related to POD datatypes - if the variable crosses its max value, its values are restart from 0:

#include <iostream>
#include <cstdint>
#include <stdexcept>

int main()
{
try
{
for (uint8_t idx = 254 ;  ; idx++)
{
std::cout << unsigned(idx) << std::endl;
}
}
catch(std::overflow_error e)
{
std::cout << "Error" << std::endl;
}
}

When I run the code the exception code is never executed - but is this the desired behavior?

Upvotes: 1

Views: 1047

Answers (4)

eerorika
eerorika

Reputation: 238461

it seems that latest C++ compiler has introduced a new functionality

No. This is how C++ has always been specified.

if the variable crosses its max value, its values are restart from 0

If an unsigned integer result of a calculation is not representable by the type, then the result will instead be the representable value that is congruent with the mathematical result modulo 2n where n is the number of bits in the representation (i.e. congruent with the largest representable value + 1).

In other words, (largest representable unsigned integer + 1) is 0, just like you observed.

Note that this rule does not apply to signed integers. Overflowing a signed integer results in undefined behaviour.

P.S. No operation on a fundamental type is specified to throw an exception. Most of the standard library functions don't throw std::overflow_error either.

Upvotes: 1

Michael Kenzel
Michael Kenzel

Reputation: 15951

unsigned int does not overflow or underflow, that's the core difference between signed and unsigned types in C++. unsigned types behave according to modulo arithmetic (i.e., they "wrap around") [basic.fundamental]/4. If you want to provoke an integer overflow, use a signed integer type. But even then, an integer overflow does not throw an exception but just lead to undefined behavior

Upvotes: 0

ShadowRanger
ShadowRanger

Reputation: 155714

Almost nothing throws std::overflow_error; overflow of unsigned values is already defined in the language standard to wrap around to 0, it's not considered an "exceptional" case, so no exception will ever be thrown for plain unsigned integer math. Per cppreference docs on integer arithmetic overflow:

Unsigned integer arithmetic is always performed modulo 2n where n is the number of bits in that particular integer. E.g. for unsigned int, adding one to UINT_MAX gives ​0​, and subtracting one from ​0​ gives UINT_MAX.

Similarly, standard library modules rarely use it:

The only standard library components that throw this exception are std::bitset::to_ulong and std::bitset::to_ullong.

The mathematical functions of the standard library components do not throw this exception (mathematical functions report overflow errors as specified in math_errhandling). Third-party libraries, however, use this. For example, boost.math throws std::overflow_error if boost::math::policies::throw_on_error is enabled (the default setting).

Upvotes: 3

Chris Uzdavinis
Chris Uzdavinis

Reputation: 6131

That is the behavior for unsigned types, according to the standard:

Standard 6.7.1/4

Unsigned integers shall obey the laws of arithmetic modulo 2n where n is the number of bits in the value representation of that particular size of integer.

Which inspires the footnote:

This implies that unsigned arithmetic does not overflow because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting unsigned integer type.

Upvotes: 2

Related Questions