Henry B.
Henry B.

Reputation: 101

Allowing signed integer overflows in C/C++

I want signed integers to overflow when they become too big. How do I achieve that without using the next biggest datatype (or when I am already at int128_t)?

For example using 8bit integers 19*12 is commonly 260, but I want the result 1 11 10 01 00 with the 9th bit cut off, thus -27.

Upvotes: 10

Views: 10712

Answers (7)

Pascal Cuoq
Pascal Cuoq

Reputation: 80255

Signed overflow is undefined in C, and that's for real.

One solution follows:

signed_result = (unsigned int)one_argument + (unsigned int)other_argument;

The above solution involves implementation-defined behavior in the final conversion from unsigned to int but do not invoke undefined behavior. With most compilation platforms' implementation-defined choices, the result is exactly the two's complement result that you expect.

Finally, an optimizing compiler for one of the numerous platforms on which implementation-defined choices force the compiler to give you the behavior you expect will compile the above code to the obvious assembly instruction.

Alternately, if you are using gcc, then the options -fwrapv/-fno-strict-overflow may be exactly what you want. They provide an additional guarantee with respect to the standard that signed overflows wrap around. I'm not sure about the difference between the two.

Upvotes: 8

caf
caf

Reputation: 239011

It is possible to do this in a correct standard C manner, so long as you have access to an unsigned type that is of the same width as your signed type (that is, has one more value bit). To demonstrate with int64_t:

int64_t mult_wrap_2scomp(int64_t a, int64_t b)
{
    uint64_t result = (uint64_t)a * (uint64_t)b;

    if (result > INT64_MAX)
        return (int64_t)(result - INT64_MAX - 1) - INT64_MAX - 1;
    else
        return (int64_t)result;
}

This does not produce any problematic intermediate results.

Upvotes: 2

jilles
jilles

Reputation: 11212

Assuming two's complement signed integer arithmetic (which is a reasonable assumption these days), for addition and subtraction, just cast to unsigned to do the calculation. For multiplication and division, ensure the operands are positive, cast to unsigned, calculate and adjust the signs.

Upvotes: 1

Lee
Lee

Reputation: 13542

It sounds like you want to do unsinged integer arithmetic, then stuff the result into a signed integer:

unsigned char a = 19;
unsigned char b = 12;

signed char c = (signed char)(a*b);

should give you what you're looking for. Let us know if it doesn't.

Upvotes: 0

Milan
Milan

Reputation: 15849

Use bigger datatypes. With GMP you will have all the space you probably need.

Upvotes: -2

Šimon Tóth
Šimon Tóth

Reputation: 36423

You could create an objective wrapper around int, but that would involve quite a lot of overhead code.

Upvotes: 1

Billy ONeal
Billy ONeal

Reputation: 106530

Signed integer overflow is undefined according to both C and C++ standards. There's no way to accomplish what you want without a specific platform in mind.

Upvotes: 1

Related Questions