is this intended behavior?

Don Clugston dac at nospam.com.au
Thu Apr 12 20:52:03 PDT 2007


James Dennett wrote:
> James Dennett wrote:
>> Don Clugston wrote:
>>> James Dennett wrote:
>>>> Don Clugston wrote:
>>>>> Derek Parnell wrote:
>>>>>> On Mon, 09 Apr 2007 15:01:56 -0400, Frank Malone wrote:
>>>>>>
>>>>>>> dmd v1.010
>>>>>>>
>>>>>>> import std.stdio;
>>>>>>> void main() {
>>>>>>>         uint a = 3;
>>>>>>>         ubyte b = 3;
>>>>>>>         int c = -1;
>>>>>>>         writefln(c < a ? "true" : "false"); // outputs false
>>>>>>>         writefln(c < b ? "true" : "false"); // outputs true
>>>>>>> }
>>>>>> Yes, kind of ... it is undefined behaviour ... the compiler doesn't
>>>>>> know
>>>>>> what to do so it does something dumb instead. I believe that a warning
>>>>>> (a.k.a "error" in Walter-speak) should be issued by the compiler.
>>>>> I agree.
>>>>> I think we should seriously consider the possibility that literals
>>>>> should be treated differently to variables, as regards signed-unsigned
>>>>> mismatches.
>>>>> * If the value fits in the range 0..int.max, it should be implicitly
>>>>> convertible to int, or to uint. --> 100% guaranteed safe.
>>>>> * If it is outside that range, an error should be issued, since it is
>>>>> definitely a bug.
>>>>>
>>>>> My feeling is, that this would eliminate most of the annoying & useless
>>>>> signed/unsigned mismatch warnings, and catch many of the real bugs.
>>>> It's a shame if a language can't make the code above
>>>> do the right thing, and the right thing is simple:
>>>> -1 is less than 3, report that.  Don't try to make
>>>> comparisons convert their arguments to a common type.
>>>>
>>>> With an int a and a uint b, "a<b" should give the
>>>> same result as "(a<0) || ((uint)a < b)" -- where the
>>>> conversion happens only in cases where it fits.  In
>>>> general, if the value of one side of the comparison
>>>> is out of range for the other side, the answer is
>>>> known without testing the other value.  Concretely,
>>>> for example, -3 < (uint)x for all x, and similarly
>>>> 257 > (ubyte)y for all y.
>>> I don't think that's necessarily true. -3 < (uint)x is quite likely to
>>> be a bug. 
>> Except in generic code, where the uint is likely to
>> depend on a type parameter.

I think there's it is still likely to be a logical error, even in that 
situation.

> Or the more common case: the function has an int and
> a uint as variables that it wishes to compare.  (Sorry,
> I didn't imagine people would think this was intended
> for literal values, when I was writing about how
> comparisons between types should work.)

Ah, OK. I might agree with you when both are variables. But I strongly 
believe that comparing an unsigned variable with a negative literal 
shouldn't be optimised away, it should be an error.

Although I think that comparing two variables which differ in both size 
AND signedness is very suspicious behaviour.

Eg
uint a;
byte b;
if (a<b) ...

Suppose a=250. Intention is catch all values in the range 250-255.
But the coder has forgotten that 'byte' is a signed type; b should have 
been a ubyte. (And in the case where a is a constant, this bug is 
actually *likely*).



More information about the Digitalmars-d mailing list