Jump to page: 1 2 3
Thread overview
Is this reasonable?
Dec 05, 2013
Steve Teale
Dec 05, 2013
H. S. Teoh
Dec 05, 2013
eles
Dec 05, 2013
Maxim Fomin
Dec 05, 2013
Jonathan M Davis
Dec 05, 2013
Maxim Fomin
Dec 05, 2013
Timon Gehr
Dec 06, 2013
H. S. Teoh
Dec 06, 2013
Timon Gehr
Dec 05, 2013
eles
Dec 06, 2013
monarch_dodra
Dec 06, 2013
Jonathan M Davis
Dec 05, 2013
Ary Borenszweig
Dec 05, 2013
H. S. Teoh
Dec 05, 2013
Ary Borenszweig
Dec 05, 2013
Maxim Fomin
Dec 05, 2013
Ary Borenszweig
Dec 05, 2013
eles
Dec 05, 2013
eles
Dec 05, 2013
Brad Anderson
Dec 06, 2013
Jonathan M Davis
Dec 06, 2013
Fra
Dec 06, 2013
Jonathan M Davis
Dec 06, 2013
Fra
Dec 06, 2013
Steve Teale
December 05, 2013
Here I feel like a beginner, but it seems very unfriendly:

import std.stdio;

struct ABC
{
   double a;
   int b;
   bool c;
}

ABC[20] aabc;

void foo(int n)
{
   writefln("n: %d, aabc.length: %d", n, aabc.length);
   if (n < aabc.length)
      writeln("A");
   else
      writeln("B");
}

void main(string[] args)
{
   int n = -1;
   foo(n);
}

This comes back with "B".

If I change the test to (n < cast(int) aabc.length), then all is well.

Is this unavoidable, or could the compiler safely make the conversion implicitly?
December 05, 2013
On Thu, Dec 05, 2013 at 06:15:37PM +0100, Steve Teale wrote:
> Here I feel like a beginner, but it seems very unfriendly:
> 
> import std.stdio;
> 
> struct ABC
> {
>    double a;
>    int b;
>    bool c;
> }
> 
> ABC[20] aabc;
> 
> void foo(int n)
> {
>    writefln("n: %d, aabc.length: %d", n, aabc.length);
>    if (n < aabc.length)
>       writeln("A");
>    else
>       writeln("B");
> }
> 
> void main(string[] args)
> {
>    int n = -1;
>    foo(n);
> }
> 
> This comes back with "B".
> 
> If I change the test to (n < cast(int) aabc.length), then all is
> well.
> 
> Is this unavoidable, or could the compiler safely make the conversion implicitly?

Comparing a signed value to an unsigned value is a risky operation. You should always compare values of like signedness, otherwise you'll run into problems like this.

You can't compare -1 to an unsigned value because if that unsigned value happens to be uint.max, then there is no machine instruction that will give the correct result (the compiler would have to substitute the code with something like:

	uint y;
	if (x < 0 || cast(uint)x < y) { ... }

which will probably introduce undesirable overhead.

The compiler also can't automatically convert aabc.length to int, because if the length is greater than int.max (which is half of uint.max), the conversion would produce a wrong negative value instead, and the comparison will fail.

So, comparing a signed value to an unsigned value is a dangerous, error-prone operation.  Sadly, dmd doesn't warn about such risky operations; it just silently casts the values. Bearophile has often complained about this, and I'm starting to agree. This is one of the places in D where subtle mistakes can creep in and the compiler fails to warn the programmer of it.


T

-- 
Real Programmers use "cat > a.out".
December 05, 2013
On Thursday, 5 December 2013 at 17:15:39 UTC, Steve Teale wrote:
>
> Is this unavoidable, or could the compiler safely make the conversion implicitly?

It is example of notorious phenomemena called "integer promotions" and "usual arithmetic conversions". It is unavoidable given Walter's decision to keep this C stuff in D.
December 05, 2013
On Thursday, December 05, 2013 19:16:29 Maxim Fomin wrote:
> On Thursday, 5 December 2013 at 17:15:39 UTC, Steve Teale wrote:
> > Is this unavoidable, or could the compiler safely make the conversion implicitly?
> 
> It is example of notorious phenomemena called "integer promotions" and "usual arithmetic conversions". It is unavoidable given Walter's decision to keep this C stuff in D.

To be fair, you can't solve the problem automatically. It's fundamentally wrong to compare signed and unsigned values, and doing either the conversion to unsigned or to signed could be wrong (or both could be wrong), depending on the values. The best that could be done would be to warn about the comparison or to make it an error.

http://d.puremagic.com/issues/show_bug.cgi?id=259

- Jonathan M Davis
December 05, 2013
On 12/5/13 2:15 PM, Steve Teale wrote:
> Here I feel like a beginner, but it seems very unfriendly:
>
> import std.stdio;
>
> struct ABC
> {
>     double a;
>     int b;
>     bool c;
> }
>
> ABC[20] aabc;
>
> void foo(int n)
> {
>     writefln("n: %d, aabc.length: %d", n, aabc.length);
>     if (n < aabc.length)
>        writeln("A");
>     else
>        writeln("B");
> }
>
> void main(string[] args)
> {
>     int n = -1;
>     foo(n);
> }
>
> This comes back with "B".
>
> If I change the test to (n < cast(int) aabc.length), then all is well.
>
> Is this unavoidable, or could the compiler safely make the conversion
> implicitly?

Cough, cough, make array length be an int.

Do you really need arrays that big? :-S

(I'm talking to Mr. D Compiler here)
December 05, 2013
On Thu, Dec 05, 2013 at 03:47:27PM -0300, Ary Borenszweig wrote: [...]
> Cough, cough, make array length be an int.
> 
> Do you really need arrays that big? :-S
> 
> (I'm talking to Mr. D Compiler here)

A negative length array makes no sense.

Plus, being a systems language, D should be able to represent an entire 64-bit address space as an array of ubytes (even if this is rarely done!). If one were to write a kernel in D, it would be laughable to use signed array lengths.


T

-- 
Stop staring at me like that! It's offens... no, you'll hurt your eyes!
December 05, 2013
On 12/5/13 4:35 PM, H. S. Teoh wrote:
> On Thu, Dec 05, 2013 at 03:47:27PM -0300, Ary Borenszweig wrote:
> [...]
>> Cough, cough, make array length be an int.
>>
>> Do you really need arrays that big? :-S
>>
>> (I'm talking to Mr. D Compiler here)
>
> A negative length array makes no sense.

Of course not. And it will never be negative. But make it signed and all the problems everyone is having several times every month will be gone forever.

>
> Plus, being a systems language, D should be able to represent an entire
> 64-bit address space as an array of ubytes (even if this is rarely
> done!). If one were to write a kernel in D, it would be laughable to use
> signed array lengths.

You can use raw pointers for that if you are going to write a kernel in D. Or you can make a struct that wraps a pointer and length, make it uint and that's it.

But to make array.length uint by default and have these surprises all of the time just because "a negative length doesn't make sense"... I don't know, I feel it's not the right way to do it.
December 05, 2013
On Thursday, 5 December 2013 at 18:26:48 UTC, Jonathan M Davis wrote:
> On Thursday, December 05, 2013 19:16:29 Maxim Fomin wrote:
>> On Thursday, 5 December 2013 at 17:15:39 UTC, Steve Teale wrote:
>> > Is this unavoidable, or could the compiler safely make the
>> > conversion implicitly?
>> 
>> It is example of notorious phenomemena called "integer
>> promotions" and "usual arithmetic conversions". It is unavoidable
>> given Walter's decision to keep this C stuff in D.
>
> To be fair, you can't solve the problem automatically. It's fundamentally
> wrong to compare signed and unsigned values, and doing either the conversion
> to unsigned or to signed could be wrong (or both could be wrong), depending on
> the values. The best that could be done would be to warn about the comparison
> or to make it an error.
>
> http://d.puremagic.com/issues/show_bug.cgi?id=259
>
> - Jonathan M Davis

Warning would be an option, but AFAIK Walter does not like warnings, so it is unlikely to be implemented.
December 05, 2013
On Thursday, 5 December 2013 at 19:51:52 UTC, Ary Borenszweig wrote:
>
> But to make array.length uint by default and have these surprises all of the time just because "a negative length doesn't make sense"... I don't know, I feel it's not the right way to do it.

Length of array type is not uint by default. This is second issue in array.length.
December 05, 2013
On 12/5/13 4:59 PM, Maxim Fomin wrote:
>> t and have these surprises all of the time just because "a negative
>> length doesn't make sense"... I don't know, I feel it's not the right
>> way to do it.

ulong, it's the same thing.
« First   ‹ Prev
1 2 3