is this intended behavior?

James Dennett jdennett at acm.org
Wed Apr 11 20:59:23 PDT 2007


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.

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.)

It's perfectly reasonable to compare unknown values of
two different integral types.  It's *unreasonable* for
such a conversion to compile and then not follow the
rules I give, because it will lead to bugs.  It's been
tried (C, C++) and the consequences are fairly well
known -- bugs, compiler warnings to try to avoid the
bugs, casts to try to avoid the compiler warnings but
without fixing the bugs, and so on.

-- James



More information about the Digitalmars-d mailing list