Jump to page: 1 2
Thread overview
is this intended behavior?
Apr 09, 2007
Frank Malone
Apr 09, 2007
unknown
Apr 09, 2007
John Demme
Apr 09, 2007
Tom S
Apr 10, 2007
Dan
Apr 10, 2007
Pragma
Apr 09, 2007
Derek Parnell
Apr 10, 2007
Don Clugston
Apr 11, 2007
James Dennett
Apr 11, 2007
Don Clugston
Apr 12, 2007
James Dennett
Apr 12, 2007
James Dennett
Apr 13, 2007
Don Clugston
Apr 18, 2007
Serg Kovrov
April 09, 2007
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
}

April 09, 2007
Frank Malone Wrote:
>         writefln(c < a ? "true" : "false"); // outputs false

From the documentation:
> It is an error to have one operand be signed and the other unsigned for a <, <=, > or >= expression. Use casts to make both operands signed or both operands unsigned.

Please read the documentation or post to the learn forum. thx.

unknown []
April 09, 2007
unknown wrote:

> Frank Malone Wrote:
>>         writefln(c < a ? "true" : "false"); // outputs false
> 
> From the documentation:
>> It is an error to have one operand be signed and the other unsigned for a <, <=, > or >= expression. Use casts to make both operands signed or both operands unsigned.
> 
> Please read the documentation or post to the learn forum. thx.
> 
> unknown []

In all fairness, DMD should catch it at compile time and throw an error.  It doesn't even spit out a warning.  I'd consider this a bug- the code shouldn't compile, or at least a warning should be issued.

-- 
~John Demme
me@teqdruid.com
http://www.teqdruid.com/
April 09, 2007
John Demme wrote:
> unknown wrote:
> 
>> Frank Malone Wrote:
>>>         writefln(c < a ? "true" : "false"); // outputs false
>> From the documentation:
>>> It is an error to have one operand be signed and the other unsigned
>>> for a <, <=, > or >= expression. Use casts to make both operands
>>> signed or both operands unsigned.
>> Please read the documentation or post to the learn forum. thx.
>>
>> unknown []
> 
> In all fairness, DMD should catch it at compile time and throw an error.  It
> doesn't even spit out a warning.  I'd consider this a bug- the code
> shouldn't compile, or at least a warning should be issued.

Couldn't agree more. I've tripped on this exact issue a few times and seen numerous other people suffer from it.


--
Tomasz Stachowiak
April 09, 2007
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.

-- 
Derek Parnell
Melbourne, Australia
"Justice for David Hicks!"
skype: derek.j.parnell
April 10, 2007
Tom S Wrote:

> John Demme wrote:
> > unknown wrote:
> > 
> >> Frank Malone Wrote:
> >>>         writefln(c < a ? "true" : "false"); // outputs false

What it appears to be doing incorrectly is attempting to convert -1 to an unsigned value to compute the comparison; which should produce uint.max; while the ubyte may be converting to a uint as well.

(int < ubyte) ought to be reasonable to use.  The fact it isn't never occurred to me, and would demonstrate that the language is still lacking in a couple quite fundamental areas.
April 10, 2007
Dan wrote:
> Tom S Wrote:
> 
>> John Demme wrote:
>>> unknown wrote:
>>>
>>>> Frank Malone Wrote:
>>>>>         writefln(c < a ? "true" : "false"); // outputs false
> 
> What it appears to be doing incorrectly is attempting to convert -1 to an unsigned value to compute the comparison; which should produce uint.max; while the ubyte may be converting to a uint as well.
>
> (int < ubyte) ought to be reasonable to use.  The fact it isn't never occurred to me, and would demonstrate that the language is still lacking in a couple quite fundamental areas.

What makes this a big WTF, is that the conversion from int to uint is done on the opposite side of the comparison as the conversion from ubyte to int.  It's almost as if the compiler tries to implicitly convert the right-hand side, fails, then attempts to implicitly convert the left, and passes.

IMO, behavior that complicated (and subtle!) should be defined, and documented if not labeled a bug.  Either that, or it should force a cast() in cases where mixed types can yield unpredictable results.


-- 
- EricAnderton at yahoo
April 10, 2007
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.

April 11, 2007
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.

-- James
April 11, 2007
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. I would want an error message if I ever wrote that -- it doesn't make sense. OTOH (uint)x > 3 makes perfect sense, as does (int)x>3.

The underlying problem is that uint doesn't necessarily mean "positive integer", it just means "no sign bit"; it could be the low part of a multi-byte integer, for example. Whereas a positive literal in the range 0..int.max has no such ambiguity.
« First   ‹ Prev
1 2