views:

62

answers:

1

I'm making an attempt to learn C++ over again, using Sams Teach Yourself C++ in 21 Days (6th ed.). I'm trying to work through it very thoroughly, making sure I understand each chapter (although I'm acquainted with C-syntax languages already).

Near the start of chapter 5 (Listing 5.2), a point is made about unsigned integer overflow. Based on their example I wrote this:

#include <iostream>

int main () {
    unsigned int bignum = 100;
    unsigned int smallnum = 50;
    unsigned int udiff;
    int diff;
    udiff = bignum - smallnum;
    std::cout << "Difference (1) is " << udiff << "\n";
    udiff = smallnum - bignum;
    std::cout << "Difference (2) is " << udiff << "\n";
    diff = bignum - smallnum;
    std::cout << "Difference (3) is " << diff << "\n";
    diff = smallnum - bignum;
    std::cout << "Difference (4) is " << diff << "\n";
    return 0;
}

This gives the following output, which is not surprising to me:

Difference (1) is 50
Difference (2) is 4294967246
Difference (3) is 50
Difference (4) is -50

If I change the program so that the line declaring bignum reads instead unsigned int bignum = 3000000000; then the output is instead

Difference (1) is 2999999950
Difference (2) is 1294967346
Difference (3) is -1294967346
Difference (4) is 1294967346

The first of these is obviously fine. The number 1294967346 is explained by the fact that 1294967346 is precisely 2^32 - 3000000000. I don't understand why the second line doesn't read 1294967396, owing to the 50 contributed by smallnum.

The third and fourth lines I can't explain. How do these results come about?

Edit: For the third line - does it give this result just by finding the solution modulo 2^32 that fits in the range of values allowed for a signed int?

+1  A: 

2^32 - 3000000000 = 1294967296 (!)

Oli Charlesworth
2^32 - 3000000000 is quite a bit smaller than 1294967296 factorial.
Dingo
Yes, you are right. Could you give me some idea of how the third one happens?
Hammerite
The third one is technically implementation-defined. But in practice, on a two's-complement architecture is that `bignum - smallnum` evaluates to 2999999950. This is then assigned to a `signed int`, which will basically reinterpret the underlying bits without modifying them. This results in -1294967346. The C standard says that *"[if] the new type is signed and the value cannot be represented in it; either theresult is implementation-defined or an implementation-defined signal is raised"*.
Oli Charlesworth
Great, thanks for your help in understanding this.
Hammerite