4 ms·
I meant the consequences of the two-complement system is known. There are tons of quirks in C, but abs() doesn't make the list in my book. It is just that the
by tjoff 5y ago
I meant the consequences of the two-complement system is known.
There are tons of quirks in C, but abs() doesn't make the list in my book. It is just that the underlying representation (in the case of two-complement) doesn't allow for it to exist.
- tialaramex 5y ago> I meant the consequences of the two-complement system is known. How does that matter? We're calling abs() which is not defined over the "two-complement system" it's defined on C's signed integer type, and the way it's defined is that if you call it with the valid integer INT_MIN you get Undefined Behaviour. Let me underscore that, you don't necessarily get zero, or INT_MAX or five, or even INT_MIN (which might feel pretty unexpected given you just called abs and now you've got a negative number again - but is at least a defined behaviour) you get Undefined Behaviour. All bets are off. The programmer who gets bitten by this isn't thinking about INT_MIN, they're thinking about how to check the input is in range, they've written abs(x) < 100 and they think this means they checked that x is between -99 and +99 inclusive, but they're wrong, what it did was introduce Undefined Behaviour into their program whenever x is INT_MIN.
- tjoff 5y ago>How does that matter? Because C is a low level language. It is not a mistake, it by design exposes hardware characteristics. If you don't care about that you probably shouldn't be using C. I am the first to agree that undefined behavior in C is pretty bad. But this is trivially understood and one of the most basic examples. Can it still bite you in the ass? Sure. I would prefer it to be implementation defined, but relying on that blindly isn't much better anyway.
- tialaramex 5y agoUndefined Behaviour doesn't "expose hardware characteristics". I assure you that the effect in hardware is not undefined. It would be interesting to survey Rust programs here. Rust's abs() on normal signed integer types function panics on overflow except in release builds (where it does the same as wrapping_abs) Rust's wrapping_abs() gives MIN because that's what happens in two's complement arithmetic when you wrap around beyond MAX, this is probably undesirable for most people most of the time. Rust's saturating_abs() gives MAX here, I would expect lots of programmers want that. The Wrapping<T> and Saturating<T> types have abs() do what wrapping_abs() or saturating_abs() accordingly do on the basic integer type.
- tjoff 5y agoReally struggling what your point is. I didn't say that undefined behavior expose hardware characteristics, though I suppose for a lot of cases it really does - but the compiler won't assume so. I said that C exposes hardware characteristics. And C also has several architectures in mind. Signed integer overflow is trivial on a two-complement system but not necessarily on others, so the lowest common denominator dictates what can be done. If the behavior is different or expensive you might shift that decision to the programmer. Negating the sign of INT_MIN isn't cheap to do in a two-complement system.
- tialaramex 5y ago> I said that C exposes hardware characteristics. Nonsense isn't a characteristic of the hardware. The hardware has very clearly defined behaviour, but C chooses not to expose that.
- tjoff 5y agoWell, how do you expose something that is different on different architectures? Maybe not define it? Anyway, doesn't seem like you are even trying to understand. No worries, I won't bother.
- tialaramex 5y agoC is full of things that are different from one architecture to the next but don't have Undefined Behaviour. Instead they are: "Implementation Defined".
- deleted 5y ago[deleted]
- CamperBob2 5y agoThis argument is a nonstarter. abs() can't return a defined answer if you pass INT_MIN to it because there is no such thing as abs(INT_MIN) in the two's-complement system used by virtually all real-world systems. Meanwhile, -2322 is a valid int on every C system but not an ASCII whitespace character on any of them. Therefore, it would be not only possible but perfectly reasonable for isspace() to return 0 for it. Classic violation of the principle of least surprise.