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