HCSF
HCSF

Reputation: 2649

Arithmetic overflow in C++17

  1. Is arithmetic overflow well defined per C++17 for uint8_t, uint16_t ,uint32_t, uint64_t? If yes, what are the defined behavior (excerpt from C++ standard is highly appreciated)
  2. Is arithmetic overflow well defined per C++17 for int8_t, int16_t ,int32_t, int64_t? (excerpt from C++ standard is highly appreciated)
  3. If any or all of above is implementation specific, what are the definitions for g++ and clang?
  4. If it is architecture specific (as Havenard pointed out), my question is specific to x86(-64).
  5. What if I do smaller unsigned int - bigger unsigned int, is it well-defined?

I saw the first answer of this post mentions that to my question #1, it is defined in C standard although he didn't quote it and I can't find anything about in C++ standard.

=================

Update 1:

removed "underflow" per ach as it is the wrong term (thanks @ach). Added #5 to express what I really meant by "underflow" (incorrectly)

Upvotes: 2

Views: 871

Answers (1)

SergeyA
SergeyA

Reputation: 62563

In hopes of creating a canonical, here are some normative specs (quotes taken from the latest C++ draft):

  • Unsigned integers do not overflow: see 6.7.1:

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. (44) 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.

  • Signed integer overflow/underflow is undefined: see 7.1.4:

If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.

By the way, none of it is implementation specific, and compilers aggressively exploit over/underflows for optimization. For example, as demonstrated by the following snippet:

void a();
void b();

void foo(int k) {
    int z = k+1;
    if (z < k) {
        a();
    } else {
        b();
    }
}

https://gcc.godbolt.org/z/0re-nM - the branch is eliminated, even though on real platform due to modulo 2 representation, z could actually become lesser than k.

Upvotes: 6

Related Questions