Most active commenters

    ←back to thread

    93 points endorphine | 11 comments | | HN request time: 0.823s | source | bottom
    Show context
    uecker ◴[] No.43537642[source]
    You can implement C in completely different ways. For example, I like that signed overflow is UB because it is trivial to catch it, while unsigned wraparound - while defined - leads to extremely difficult to find bugs.
    replies(4): >>43537908 #>>43538002 #>>43538056 #>>43538186 #
    1. Strilanc ◴[] No.43538056[source]
    Could you provide the code you use to trivially catch signed overflows? My impression is the opposite: unsigned is trivial (just test `a+b < b`) while signed is annoying (especially because evaluating a potentially-overflowing expression would cause the UB I'm trying to avoid).
    replies(6): >>43538172 #>>43538229 #>>43538928 #>>43539940 #>>43539954 #>>43541133 #
    2. uecker ◴[] No.43538172[source]
    Oh, I meant it is trivial to catch bugs caused by overflow by using a sanitizer and difficult to find bugs caused by wraparound.

    But checking for signed overflow is also simply with C23: https://godbolt.org/z/ebKejW9ao

    3. ndiddy ◴[] No.43538229[source]
    Compiling with -ftrapv will cause your program to trap on signed overflow/underflow, so when you run it in a debugger you can immediately see where and why the overflow/underflow occurred.
    replies(1): >>43542268 #
    4. o11c ◴[] No.43538928[source]
    Avoiding UB for performing the signed addition/subtraction/multiplication is trivial - just cast to unsigned, do the operation, cast back. In standard C23 or GNU C11, you can write a `make_unsigned` and `make_signed` macro using `typeof` and `_Generic`.
    5. ◴[] No.43539940[source]
    6. steveklabnik ◴[] No.43539954[source]
    You're right that this test would be UB for signed integers.

    See here for that in action, as well as one way to test it that does work: https://godbolt.org/z/sca6hxer4

    If you're on C23, uercker's advice to use these standardized functions is the best, of course.

    7. amavect ◴[] No.43541133[source]
    >unsigned is trivial (just test `a+b < b`)

    Nitpicking, the test itself should avoid overflowing. Instead, test "a <= UINT_MAX - b" to prove no overflow occurs.

    For signed integers, we need to prove the following without overflowing in the test: "a+b <= INT_MAX && a+b >= INT_MIN". The algorithm follows: test "b >= 0", which implies "INT_MAX-b <= INT_MAX && a+b >= INT_MIN", so then test "a <= INT_MAX-b". Otherwise, "b < 0", which implies "INT_MIN-b >= INT_MIN && a+b <= INT_MAX", so then test "a >= INT_MIN-b".

    replies(1): >>43542957 #
    8. AlotOfReading ◴[] No.43542268[source]
    It's worth mentioning that GCC's ftrapv has been unreliable and partially broken for 20+ years at this point. It's recommended that you use the fsanitize traps instead, and there's an open ticket to switch the ftrapv implementation over to using it under the hood:

    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101521

    replies(1): >>43549143 #
    9. lelanthran ◴[] No.43542957[source]
    > Nitpicking, the test itself should avoid overflowing.

    Why? Overflowing is well defined for unsigned.

    replies(1): >>43552153 #
    10. ndiddy ◴[] No.43549143{3}[source]
    Thanks, I hadn't heard of that.
    11. amavect ◴[] No.43552153{3}[source]
    Personal preference, hence nitpicking. It forms a special case of the signed integer algorithm, which feels nice.