Jump to page: 1 210  
Page
Thread overview
Is there ANY chance we can fix the bitwise operator precedence rules?
Jun 18, 2010
Don
Jun 18, 2010
Simen kjaeraas
Jun 18, 2010
Tomek Sowiński
Jun 19, 2010
BCS
Jun 19, 2010
Don
Jun 19, 2010
Justin Johansson
Jun 19, 2010
BCS
Jun 19, 2010
Leandro Lucarella
Re: Is there ANY chance we can fix the bitwise operator precedence
Jun 20, 2010
bearophile
Re: Is there ANY chance we can fix the bitwise operator precedence
Jun 20, 2010
bearophile
Re: Is there ANY chance we can fix the bitwise operator precedence
Jun 20, 2010
Sean Kelly
Jun 20, 2010
bearophile
Jun 21, 2010
Sean Kelly
Jun 21, 2010
bearophile
Jun 21, 2010
Michel Fortin
Jun 21, 2010
bearophile
Jun 21, 2010
bearophile
Jun 21, 2010
BCS
Jun 21, 2010
bearophile
Jun 21, 2010
Don
Jun 21, 2010
KennyTM~
Jun 21, 2010
bearophile
Jun 21, 2010
Don
Jun 22, 2010
Leandro Lucarella
Re: Is there ANY chance we can fix the bitwise operator precedence
Jun 21, 2010
bearophile
Jun 18, 2010
bearophile
Jun 18, 2010
bearophile
Jun 18, 2010
Jonathan M Davis
Jun 18, 2010
bearophile
Jun 19, 2010
Jonathan M Davis
Jun 19, 2010
Jonathan M Davis
Jun 19, 2010
bearophile
Jun 19, 2010
bearophile
Jun 19, 2010
Jonathan M Davis
Jun 19, 2010
Robert Jacques
Jun 19, 2010
Vladimir Panteleev
Jun 19, 2010
Jonathan M Davis
Jun 19, 2010
Leandro Lucarella
Jun 19, 2010
Jonathan M Davis
Jun 19, 2010
KennyTM~
Re: Is there ANY chance we can fix the bitwise operator precedence
Jun 19, 2010
bearophile
Jun 19, 2010
KennyTM~
Jun 21, 2010
Jonathan M Davis
Jun 21, 2010
Sean Kelly
Jun 21, 2010
bearophile
Jun 21, 2010
Sean Kelly
Jun 21, 2010
Ellery Newcomer
Jun 22, 2010
Leandro Lucarella
Jun 22, 2010
Bill Baxter
Jun 22, 2010
Leandro Lucarella
Jun 22, 2010
Bill Baxter
Jun 22, 2010
Leandro Lucarella
Jun 22, 2010
Adam Ruppe
Jun 22, 2010
Adam Ruppe
Jun 22, 2010
Don
Jun 22, 2010
Adam Ruppe
Jun 22, 2010
Leandro Lucarella
Jun 22, 2010
Don
Jun 22, 2010
Leandro Lucarella
Jun 22, 2010
Adam Ruppe
Jun 22, 2010
Simen kjaeraas
Jun 21, 2010
Jonathan M Davis
Jun 21, 2010
Don
Jun 21, 2010
Jonathan M Davis
Jun 21, 2010
Jonathan M Davis
Jun 21, 2010
Jonathan M Davis
Jun 22, 2010
Bill Baxter
Re: Is there ANY chance we can fix the bitwise operator precedence
Jun 21, 2010
bearophile
Jun 22, 2010
Jonathan M Davis
Jun 22, 2010
Leandro Lucarella
Jun 22, 2010
BCS
Jun 22, 2010
Jonathan M Davis
Jun 21, 2010
Sean Kelly
Jun 21, 2010
Jeff Nowakowski
Jun 22, 2010
Don
Jun 22, 2010
Jeff Nowakowski
Jun 22, 2010
Don
Jun 22, 2010
Jeff Nowakowski
Jun 19, 2010
Robert Jacques
June 18, 2010
In the comments for bug 4077, "Bugs caused by bitwise operator precedence"
it was asked why C gave & with lower precedence than ==, when it is unintuitive and a frequent source of bugs.

I was quite shocked to find that the reason is backwards compatibility with the B programming language.

Denis Ritchie says (http://cm.bell-labs.com/cm/cs/who/dmr/chist.html):
--------------------
At the suggestion of Alan Snyder, I introduced the && and || operators to make the mechanism [[short circuit evaluation]] more explicit.

Their tardy introduction explains an infelicity of C's precedence rules. In B one writes

    if (a==b & c) ...

to check whether a equals b and c is non-zero; in such a conditional expression it is better that & have lower precedence than ==. In converting from B to C, one wants to replace & by && in such a statement; to make the conversion less painful, we decided to keep the precedence of the & operator the same relative to ==, and merely split the precedence of && slightly from &. Today, it seems that it would have been preferable to move the relative precedences of & and
==, and thereby simplify a common C idiom: to test a masked value against another value, one must write

    if ((a&mask) == b) ...

where the inner parentheses are required but easily forgotten.
-----------------------------------
Tragic. Can we end this madness?

Could we give & | ^ the same precedence as ==, making
(a & mask == b) an error, just as (a < b == c) is rejected?
That way we could lay this common bug to rest. I've personally lost days of my life to this one. It's a bug 100% of the time.

Or is too late to break backwards compatibility with B ?

BTW I think this a great cautionary tale about the dangers of rating backwards compatibility too highly.
June 18, 2010
Don <nospam@nospam.com> wrote:

> I was quite shocked to find that the reason is backwards compatibility with the B programming language.

Surely it is important that all B code ported to D compiles correctly? :p

But yes, end the madness. I fear Walter will only do it if it provably
breaks no code, though.

I just thought through this agin. WTF?

-- 
Simen
June 18, 2010
Dnia 18-06-2010 o 23:11:43 Simen kjaeraas <simen.kjaras@gmail.com> napisał(a):

> But yes, end the madness. I fear Walter will only do it if it provably
> breaks no code, though.

if (a==b & c) would be flagged as error. If it breaks loudly, that's ok. Besides, it's not much used anyway. Ban it.

Tomek
June 18, 2010
Don wrote:
[snip]
> Or is too late to break backwards compatibility with B ?

We can and should do it. It won't impact TDPL adversely.

A perhaps little known thing is that D doesn't allow this:

int a, b, c;
if (a < b < c) { ... }

although it's compilable code in C. The same strategy could be used for combinations of badly-prioritized operators: the language could just require the user to add parens.


Andrei
June 18, 2010
Don:

> Tragic. Can we end this madness?
> Could we give & | ^ the same precedence as ==, making
> (a & mask == b) an error, just as (a < b == c) is rejected?
> That way we could lay this common bug to rest.

You can change the dmd compiler (even D1, if you want) applying this change and create a compiled "experiment version" that people can try (even people that don't compile dmd every day), to see possible side effects of this change, use it to spot bugs in their D code or inside Phobos, etc.


> BTW I think this a great cautionary tale about the dangers of rating backwards compatibility too highly.

Beside that one, there are few other parts of C/D code that I'd like still to turn into syntax errors in D2, like:

1) Implicit string concat (bug 3827, with an incomplete patch):

string[] a = ["foo", "bar" "baz"];

2) switch cases that don't end with goto or break:

void main() {
    int x, y;
    switch (x) {
        case 0: y++;
        default: y--;
    }
}


3) Several usages of C comma operator.

And few others that I don't remember now.

----------------

Andrei Alexandrescu:

> A perhaps little known thing is that D doesn't allow this:
> int a, b, c;
> if (a < b < c) { ... }
> although it's compilable code in C.

It's a pity C compatibily forbids to use that syntax in D, because chained comparison operator syntax is handy in Python to tell if a value is in a range:

>>> 1 < 5 < 10
True
>>> "hello" < "zeta" < "red"
False

Bye,
bearophile
June 18, 2010
bearophile:
> >>> 1 < 5 < 10
> True

It's especially useful when the value in the middle is the result of some function call:

if 1 < foo(5) < 10: ...

In D you have to use a temporary variable:
auto aux = foo(5);
if (1 < aux && aux < 10) { ...

Bye,
bearophile
June 18, 2010
bearophile wrote:

> 2) switch cases that don't end with goto or break:
> 
> void main() {
>     int x, y;
>     switch (x) {
>         case 0: y++;
>         default: y--;
>     }
> }

I, for one, _want_ case statements to be able to fall through. It would be horribly painful in many cases if they couldn't. Now, requiring a separate statement like fallthrough or somesuch instead of break might not be a bad idea, but requiring that each case end with a break would seriously restrict the usefulness of switch statements.

- Jonathan M Davis
June 18, 2010
Jonathan M Davis:
> but requiring that each case end with a break would seriously restrict the usefulness of switch statements.

Time ago there was a long thread about this topic (and in the meantime Walter has added the "static switch" that burns the fat chance to add to D2 a second safer switch that fixes both the common kind of bugs caused by C switch statements and not just the enum-switch bugs avoided by the current static switch!) and I am not sure it's right to restart that discussion again. Anyway, can you show me one example where requiring that each case end with a break OR goto restricts the usefulness of switch statements?

Bye,
bearophile
June 19, 2010
bearophile wrote:

> Jonathan M Davis:
>> but requiring that each case end with a break would seriously restrict the usefulness of switch statements.
> 
> Time ago there was a long thread about this topic (and in the meantime Walter has added the "static switch" that burns the fat chance to add to D2 a second safer switch that fixes both the common kind of bugs caused by C switch statements and not just the enum-switch bugs avoided by the current static switch!) and I am not sure it's right to restart that discussion again. Anyway, can you show me one example where requiring that each case end with a break OR goto restricts the usefulness of switch statements?
> 
> Bye,
> bearophile

Well, I would pount out that you mentioning it more or less reopens the discussion, but in any case, the simplest answer would be if you have multiple values for the variable that your switching on which should all be using the same kind. Fortunately, D simplifies that by allowing you to put multiple values with a single case. An extension of that is if you have two cases which are almost identical but where one of them needs to do something first before the code that is common between both cases.

A more complicated example would be one where you're doing something like Duff's Device:

send(to, from, count)
register short *to, *from;
register count;
{
        register n=(count+7)/8;
        switch(count%8){
        case 0: do{     *to = *from++;
        case 7:         *to = *from++;
        case 6:         *to = *from++;
        case 5:         *to = *from++;
        case 4:         *to = *from++;
        case 3:         *to = *from++;
        case 2:         *to = *from++;
        case 1:         *to = *from++;
                }while(--n>0);
        }
}

Even if you drop the whole issue of the loop interleaving with the case statements in Duff's Device, you could still have a situation where you would have a series of things that should be done with how many of them you do depending on what the value you're switching on and you doing all of the preceding ones for each greater value. e.g.

switch(value)
{
    case 0:
        do something...
    case 1:
        do something else...
    case 2:
        do a third thing...
    case 3:
        do yet more...
}

If value were 0, you'd need to do everything that is done at each case statement, while if it were 2, you'd only need to do whatever is done for 2 and 3.

I grant you that in most cases, you don't need to do that sort of thing and that missing a break is an error, but there are definitely cases where being able to have case statements fall through can be quite handy. If it wouldn't likely break compatability with C/C++, I'd suggest requiring a continue if you wanted to fall through (since that wouldn't require a new keyword), but I think that that would break compatibility in cases where the switch is in a loop, so that's probably a no-go, and I very much doubt that Walter would want to add the keyword fallthrough or something similar.

It is an issue, but it's a well-known one, and I don't think that requiring a break is worth the loss of power. If we push for a change, it should probably be in requiring a keyword to indicate that you meant to fall through. That would give you the safety without losing the power.

- Jonathan M Davis
June 19, 2010
Jonathan M Davis wrote:

...
> the simplest answer would be if you have
> multiple values for the variable that your switching on which should all
> be using the same kind.
...

Yikes, that should be "using the same _code_."
« First   ‹ Prev
1 2 3 4 5 6 7 8 9 10