Treating the abusive unsigned syndrome

Don nospam at nospam.com
Wed Nov 26 01:18:49 PST 2008


Andrei Alexandrescu wrote:
> D pursues compatibility with C and C++ in the following manner: if a 
> code snippet compiles in both C and D or C++ and D, then it should have 
> the same semantics.
> 
> A classic problem with C and C++ integer arithmetic is that any 
> operation involving at least an unsigned integral receives automatically 
> an unsigned type, regardless of how silly that actually is, 
> semantically. About the only advantage of this rule is that it's simple. 
> IMHO it only has disadvantages from then on.
> 
> The following operations suffer from the "abusive unsigned syndrome" (u 
> is an unsigned integral, i is a signed integral):
> 
> (1) u + i, i + u
> (2) u - i, i - u
> (3) u - u
> (4) u * i, i * u, u / i, i / u, u % i, i % u (compatibility with C 
> requires that these all return unsigned, ouch)
> (5) u < i, i < u, u <= i etc. (all ordering comparisons)
> (6) -u

I think that most of these problems are caused by C enforcing a foolish 
consitency between literals and variables.
The idea that literals like '0' and '1' are of type int is absurd, and 
has caused a torrent of problems. '0' is just '0'.

uint a = 1;
does NOT contain an 'implicit conversion from int to uint', any more 
than there are implicit conversions from naturals to integers in 
mathematics. So I really like the polysemous types idea.

For example, when is it reasonable to use -u?
It's useful with literals like
uint a = -1u; which is equivalent to uint a = 0xFFFF_FFFF.
Anywhere else, it's probably a bug.

My suspicion is, that if you allowed all signed-unsigned operations when 
at least one was a literal, and made everything else illegal, you'd fix 
most of the problems. In particular, there'd be a big reduction in 
people abusing 'uint' as a primitive range-limited int.

Although it would be nice to have a type which was range-limited, 'uint' 
doesn't do it. Instead, it guarantees the number is between 0 and 
int.max*2+1 inclusive. Allowing mixed operations encourages programmers 
to focus the benefit of 'the lower bound is zero!' while forgetting that 
there is an enormous downside ('I'm saying that this could be larger 
than int.max!')

Interestingly, none of these problems exist in assembly language 
programming, where every arithmetic instruction affects the overflow 
flag (for signed operations) as well as the carry flag (for unsigned).



More information about the Digitalmars-d mailing list