A strange div bug on Linux x86_64, (both dmd & ldc2): long -5000 / size_t 2 = 9223372036854773308
Walter Bright
newshound2 at digitalmars.com
Thu Aug 13 21:33:11 UTC 2020
On 8/13/2020 3:10 AM, H. S. Teoh wrote:
> You're mixing signed and unsigned values. That's generally dangerous
> territory where integer promotion rules inherited from C/C++ take over
> and cause sometimes weird effects, like here. Changing integer promotion
> rules will probably never happen now, because it will cause massive
> *silent* breakage of existing code. So, in the spirit of defensive
> programming, I recommend avoiding mixing signed/unsigned values in this
> way.
There are some things everyone simply needs to know to use a systems programming
language successfully:
1. How 2's complement arithmetic works, especially in regard to how negative
numbers are handled.
2. The range of values (signed and unsigned) in 2's complement values.
3. Overflow is not detected.
4. 2's complement arithmetic wraps around.
5. The integral promotion rules (the issue in this thread).
I say "systems programming language" because although other languages (like
Python) take care of these issues, but that comes at a high cost in terms of
performance. Some languages (like Java) get rid of the signed/unsigned issue by
getting rid of unsigned integer types. This choice makes it very hard to do some
sorts of operations.
The choice Java made to remove unsigned integers is an indication that "just add
a warning" is not as workable as it sounds.
The integral promotions rule is in D because:
1. C/C++ programmers are very used to it. Subtly changing the rules will make
transfer of code and skills C <=> D a much riskier proposition, especially if
you're not the person who wrote that code.
2. Interoperability of C <=> D and even machine translation is far more
pragmatic if these rules are followed.
Historical Note: Before 1990, half of the C compilers used "value preserving"
integral promotions, half used "sign preserving". C was undergoing
standardization, and a great debate raged about which one was better.
Eventually, one was picked, and the other compiler vendors had to suck it up and
change, and the newly broken C code had to be fixed. ("Value preserving" was
picked, which is why ubyte promotes to int, not uint.)
These rules often do cause some difficulty with people new to C/C++/D. I know
they seem insane to them. But they aren't hard to learn, and it's well worth the
few minutes it takes to do it.
To check for overflows, etc., use core.checkedint:
https://dlang.org/phobos/core_checkedint.html
If you're willing to accept some performance reduction,
std.experimental.checkedint provides integral types that protect against all
kinds of integer arithmetic issues, including "unexpected change of sign":
https://dlang.org/phobos/std_experimental_checkedint.html
More information about the Digitalmars-d
mailing list