Binary Operator Rant



  • I woke up this morning to realize that the presedence of the binary operators in C/C++ make no fucking sense. For those of you who don't know, the binary operators have a lower precedence than the equality operators, thus (A == B | C) is equivalent to ((A == B­) | C). Who does that?

    As with everything shitty in C and C++, it turns out that it is due to backwards compatibility. Once upon a time, C had no boolean operators, and thus you had to use the binary ones instead. Thankfully they eventually realized how stupid this was, and added the boolean ones.

    And this could have been the end of the story. With the boolean operators in place, there's no reason to use the binary operators on boolean values ever again. And surely a "modern" object-oriented language like Java would learn from past mistakes? Ofcourse not. They even decided to one-up C by making the binary operators double as boolean operators, while still keeping the dedicated boolean operators. Fortunately they also decided to not let you implicitly cast integers to compensate. Woohoo.

    And when I say "like Java", I mean just about every fucking programming language ever. Except Python. This must be why someone thought Lisp would be a good idea.



    Bonus mini-rant:
    Where the hell is the boolean XOR operator anyway? Do the language developers have an irrational fear of furry emoticons? Or did they just implement AND and OR, then though fuck it let's go drink ourselves to death?



  • @Faxmachinen said:

    Bonus mini-rant:

    Where the hell is the boolean XOR operator anyway? Do the language developers have an irrational fear of furry emoticons? Or did they just implement AND and OR, then though fuck it let's go drink ourselves to death?

    Here: !=

    Now granted, it doesn't force conversion of its parameters to booleans, but when used on booleans it behaves exactly like xor. A few times I've used constructs like (a==something) != (b==whatever).



  • @tdb said:

    @Faxmachinen said:

    Bonus mini-rant:
    Where the hell is the boolean XOR operator anyway? Do the language developers have an irrational fear of furry emoticons? Or did they just implement AND and OR, then though fuck it let's go drink ourselves to death?

    Here: !=

    Why had it never occurred to me that != acted exactly like a XOR when used on booleans...?! You've enlightened me today. :)

     



  • @Elusive Pete said:

    @tdb said:

    @Faxmachinen said:

    Bonus mini-rant:
    Where the hell is the boolean XOR operator anyway? Do the language developers have an irrational fear of furry emoticons? Or did they just implement AND and OR, then though fuck it let's go drink ourselves to death?

    Here: !=

    Why had it never occurred to me that != acted exactly like a XOR when used on booleans...?! You've enlightened me today. :)

    Same for me... thx for this smart and simple trick.

     



  • @Elusive Pete said:

    Why had it never occurred to me that != acted exactly like a XOR when used on booleans...?!
    When used in a loosely typed language, you can also use:
    !a != !b
    This will cast to boolean first (the NOT operator will then invert the boolean value, but that's harmless, since it gets the same result), then get the same answer as boolean!=boolean



  • @Elusive Pete said:

    You've enlightened me today. :)
     

    Both 1st and 2nd posts have blown my mind.



  • Thanks for the 1st and 2nd posts.

    As for precedence, I always say you should never trust it, since I think it may vary depending on the compiler you use. Parenthesis can be a dev's best friends there.



  • [quote user="Renan "C#" Sousa"]

    As for precedence, I always say you should never trust it, since I think it may vary depending on the compiler you use.

    [/quote]  No.  Well, unless you're comparing compilers for entirely different languages, but all the mainstream languages have well-defined specifications with well-defined operator precedence and there aren't any mainstream compilers that I know of that screw it up.  While your advice to use parentheses liberally is good advice in general (for reasons related to human-readabililty and the likely failings of human memory when writing code), your suggested reason for doing so is cargo-cult I'm afraid.

    Can you actually find an example?  Because if there is such a buggy compiler out there, I'd rather avoid it.



  •  While I agree that a complier that breaks something as fundamental as operator precedence should be immediately deep-sixed, there's another and, IMO stronger reason for using parentheses liberally:

     

    When someone else is maintaining your code and you've minimised the number of tokens by omitting every not-strictly-necessary  parenthesis, then that next programmer has to ask himself - "Am I sure  that the original coder knew the precedence rules?" 

    Fully parenthesising (or at least in any case where it's not absolutely trivial:  (a*b) + c for example is overkill, 

     

    But if I see a | b << c, then I have to wonder if the original coder knew that the shift takes precedence over the bitwise OR or if that's where I should start looking harder. Parenthesising this to  a | (b << c) tells me what they wanted the compiled code to do and that makes debugging/modifying much easier. And yes, I've seen some pretty horrible mistakes made with precedence of shifts, ANDs and ORs by otherwise quite solid coders. I probably have done that once or twice myself, but nowadays I try to fully parenthesise wherever I think there could be the slightest doubt in my or the next coder's understanding

     

     



  • @jes said:

     While I agree that a complier that breaks something as fundamental as operator precedence should be immediately deep-sixed, there's another and, IMO stronger reason for using parentheses liberally:

    When someone else is maintaining your code [ ... ]

    Actually, that isn't "another" reason, it's exactly the same one that I summarised as "reasons related to human-readabililty and the likely failings of human memory when writing code".  Thanks for enlarging upon my somewhat concisely-expressed point though.

     



  • @DaveK said:

    Actually, that isn't "another" reason, it's exactly the same one that I summarised as "reasons related to human-readabililty and the likely failings of human memory when writing code".  Thanks for enlarging upon my somewhat concisely-expressed point though.

    When someone else is reading your post and you've minimised the number of words by omitting every not-strictly-necessary thought, then that next forum user has to ask himself - "Am I sure that the original poster knew the current topic?"



  •  As for java, && is the lazy version of &, || is the lazy version of |.

     Beginning programmers understand neither, lazy boolean operators are difficult, and the non-lazy versions happily work on non-boolean variables, performing the bitwise operation.

     Not to mention i'm now starting to wonder why we shouldn't use the XOR ^ in java instead of !=. Perhaps i'll start to do that when i want to mess around with people :D

     I find it more stunning that i can use the bitwise XOR as unequal operator on booleans, then using != for XOR operations.



  • @Xyro said:

    @DaveK said:
    Actually, that isn't "another" reason, it's exactly the same one that I summarised as "reasons related to human-readabililty and the likely failings of human memory when writing code".  Thanks for enlarging upon my somewhat concisely-expressed point though.

    When someone else is reading your post and you've minimised the number of words by omitting every not-strictly-necessary thought, then that next forum user has to ask himself - "Am I sure that the original poster knew the current topic?"

    It should have been perfectly clear what I meant.  After all, I did put it in parentheses!

     



  • PHP lets you say `$cond1 xor $cond2`, in addition to `$cond1 and $cond2` and `$cond1 or $cond2`. From what I can infer from the docs, though, they're at an even lower precedence then the regular boolean operators.

    And VB still uses the same operators for binary and boolean operations, not that it doesn't have worse annoyances.



  • @Faxmachinen said:

    I woke up this morning to realize that the presedence of the binary operators in C/C++ make no fucking sense. For those of you who don't know, the binary operators have a lower precedence than the equality operators, thus (A == B | C) is equivalent to ((A == B) | C). Who does that?

    As with everything shitty in C and C++, it turns out that it is due to backwards compatibility. Once upon a time, C had no boolean operators, and thus you had to use the binary ones instead. Thankfully they eventually realized how stupid this was, and added the boolean ones.

    And this could have been the end of the story. With the boolean operators in place, there's no reason to use the binary operators on boolean values ever again. And surely a "modern" object-oriented language like Java would learn from past mistakes? Ofcourse not. They even decided to one-up C by making the binary operators double as boolean operators, while still keeping the dedicated boolean operators. Fortunately they also decided to not let you implicitly cast integers to compensate. Woohoo.

    And when I say "like Java", I mean just about every fucking programming language ever. Except Python. This must be why someone thought Lisp would be a good idea.

     

    You ought to check out Pascal.  It doesn't have any of the language flaws described here:

    • "a = b and c" is evaluated as "a = (b and c)"
    • Because Pascal has an actual boolean type, as opposed to treating everything as a boolean like C does, it can implement and, or, and xor properly.  It's a syntax error to mix a boolean and a number, so you don't have any bitwise/logical (binary) operator confusion.
    • It has a logical xor operator.

     



  • If you have trouble memorizing the precedence rules for any language, here is an easy pneumonic to remember them by:

     

    Multiply/Divide comes before Add/Subtract.

    Use parenthesis for everything else.

     

    If I was code reviewing something and I saw "A == B | C", I would fail it in a heartbeat.



  • @MiffTheFox said:

    PHP lets you say `$cond1 xor $cond2`, in addition to `$cond1 and $cond2` and `$cond1 or $cond2`. From what I can infer from the docs, though, they're at an even lower precedence then the regular boolean operators.
    In PHP, and and or are at a lower precedence than the ternary operator. They're even lower than assignments!

    Which means you can write code this: $result = mayAFalsyValue() or $error = "WTF? This is really strange!"



  • @Faxmachinen said:

    ................. With the boolean operators in place, there's no reason to use the binary operators on boolean values ever again...............

     

     

    In embedded c particually building drivers i tend to use them every hour of the day.

     

    I was porting a project today and came across this gem with no comments:

    if ((((oldrelays ^ relays) & relays)!=0) || (((flags & (1 << oldvirelay))==0) && (PCDR & 1<<viobit))) delay(10000);

     

    At least the last guy did use a bracket or two.

     



  • @Zecc said:

    @MiffTheFox said:

    PHP lets you say $cond1 xor $cond2, in addition to $cond1 and $cond2 and $cond1 or $cond2. From what I can infer from the docs, though, they're at an even lower precedence then the regular boolean operators.
    In PHP, and and or are at a lower precedence than the ternary operator. They're even lower than assignments!

    Which means you can write code this: $result = mayAFalsyValue() or $error = "WTF? This is really strange!"

    Looks like its Perlish history is leaking through. Good old Perl, where you can write

    
    my $dhb = DBI->connect( $to_database ) or die $!
    

    Hard to find a better language!

    
    find_better_language() or die $!
    


  • @Helix said:

    if ((((oldrelays ^ relays) & relays)!=0) || (((flags & (1 << oldvirelay))==0) && (PCDR & 1<<viobit))) delay(10000);

    Let's see...

    ((oldrelays ^ relays) & relays)!=0

    The xor returns 1-bits for all relays that have changed state, then the and masks out those that are currently inactive. So this checks if any relays have change state to active (assuming 1=active and 0=inactive; without schematics of the hardware I can't know).

    (flags & (1 << oldvirelay))==0

    I don't know what flags those are, but the shift seems like oldvirelay is a relay index. The "old" hints that it applies to the previous iteration. And the flag for that relay must be cleared.

    (PCDR & 1<<viobit)

    PCDR looks like a microcontroller register, quite possibly used for digital input in this application. viobit looks like another bit index, so I'm guessing this checks whether an I/O line is high. Based on this single line I can only guess that the I/O line is somehow related to the relay indicated by oldvirelay. Maybe a feedback of some sort.

    So, if a relay has just gone active, or some specific relay does not have a flag set and a related I/O line is high, we wait for a while. Is that microseconds? The check might be to avoid activating too many relays in a too short timeframe.



  • @Zecc said:

    In PHP, and and or are at a lower precedence than the ternary operator. They're even lower than assignments!
     

    In PHP, and and or are also semantically distinct from && and ||.



  • @Xyro said:

    Looks like its Perlish history is leaking through. Good old Perl, where you can write

    
    my $dhb = DBI->connect( $to_database ) or die $!

    I believe this is a common pattern in PHP:

    $link = mysql_connect("localhost", "root", "hunter2") or die("Cannot connect to database!");

     

    @tdb said:

    a related I/O line is high
    Who's been given pot to the I/O lines?

    @da Doctah said:

    In PHP, and and or are also semantically distinct from && and ||.
    Is it? How?


  • Discourse touched me in a no-no place

    @da Doctah said:

    @Zecc said:

    In PHP, and and or are at a lower precedence than the ternary operator. They're even lower than assignments!
     

    In PHP, and and or are also semantically distinct from && and ||.

    I get the impression they're more like C's && and ||, where they're not only operators, but sequence points, and thus become 'shortcuts' - if the result of the whole expression can be figured out from the bit before the operator, then the bit after isn't even looked at.



    Hence the idioms:

    dosomething or die(); - if dosomething returns true then die() doesn't happen

    if (pointer && *pointer).... - if pointer is null, don't dereference it


  • BINNED

    @Sutherlands said:

    If you have trouble memorizing the precedence rules for any language, here is an easy pneumonic to remember them by:

     

    Multiply/Divide comes before Add/Subtract.

    Use parenthesis for everything else.

     

    That's good advice even if you can remember the precedence rules.


  • @PJH said:

    @da Doctah said:

    @Zecc said:

    In PHP, and and or are at a lower precedence than the ternary operator. They're even lower than assignments!
     

    In PHP, and and or are also semantically distinct from && and ||.

    I get the impression they're more like C's && and ||, where they're not only operators, but sequence points, and thus become 'shortcuts' - if the result of the whole expression can be figured out from the bit before the operator, then the bit after isn't even looked at.

    Indeed.  I was about to point out, since nobody's mentioned it yet, that one of the reasons C doesn't have a boolean XOR ^^ is because it wouldn't be able to have short-circuit behaviour like && and || do.

     



  • @tdb said:

    @Helix said:

    if ((((oldrelays ^ relays) & relays)!=0) || (((flags & (1 << oldvirelay))==0) && (PCDR & 1<<viobit))) delay(10000);

    Let's see...

    ((oldrelays ^ relays) & relays)!=0

    The xor returns 1-bits for all relays that have changed state, then the and masks out those that are currently inactive. So this checks if any relays have change state to active (assuming 1=active and 0=inactive; without schematics of the hardware I can't know).

    (flags & (1 << oldvirelay))==0

    I don't know what flags those are, but the shift seems like oldvirelay is a relay index. The "old" hints that it applies to the previous iteration. And the flag for that relay must be cleared.

    (PCDR & 1<<viobit)

    PCDR looks like a microcontroller register, quite possibly used for digital input in this application. viobit looks like another bit index, so I'm guessing this checks whether an I/O line is high. Based on this single line I can only guess that the I/O line is somehow related to the relay indicated by oldvirelay. Maybe a feedback of some sort.

    So, if a relay has just gone active, or some specific relay does not have a flag set and a related I/O line is high, we wait for a while. Is that microseconds? The check might be to avoid activating too many relays in a too short timeframe.


  • ♿ (Parody)

    @DaveK said:

    Indeed. I was about to point out, since nobody's mentioned it yet, that one of the reasons C doesn't have a boolean XOR ^^ is because it wouldn't be able to have short-circuit behaviour like && and || do.

    Not that it has to, but that doesn't really make sense to me. I'd guess that it was more of a minimalist thing, since you can use the existing operators to get the same effect as a dedicated xor operator. Not really because of the short circuiting of those. Anyways, maybe the minimalist thing was more important back in the day. I guess it's a little surprising that one hasn't been proposed in subsequent standards updates (or has it?). The orthogonality and the convenience would be useful, but maybe it's not widely used enough.



  • @Zecc said:

    $link = mysql_connect("localhost", "root", "hunter2") or die("Cannot connect to database!");
     

    Wow, I thought "or die" was a singular syntax construct for try/catch. I didn't know or was a special operator.

    I don't actually do PHP. I just fuck about with it for my own site.



  • @PedanticCurmudgeon said:

    @Sutherlands said:

    If you have trouble memorizing the precedence rules for any language, here is an easy pneumonic to remember them by:

     

    Multiply/Divide comes before Add/Subtract.

    Use parenthesis for everything else.

     

    That's good advice even if you can remember the precedence rules.
    I probably should have explicitly said that, but yes, that's what I was going for.  If it's not understandable with those two rules (such as the crap in the OP), it needs refactoring.

     

    @boomzilla said:

    @DaveK said:
    Indeed. I was about to point out, since nobody's mentioned it yet, that one of the reasons C doesn't have a boolean XOR ^^ is because it wouldn't be able to have short-circuit behaviour like && and || do.
    Not that it has to, but that doesn't really make sense to me. I'd guess that it was more of a minimalist thing, since you can use the existing operators to get the same effect as a dedicated xor operator. Not really because of the short circuiting of those. Anyways, maybe the minimalist thing was more important back in the day. I guess it's a little surprising that one hasn't been proposed in subsequent standards updates (or has it?). The orthogonality and the convenience would be useful, but maybe it's not widely used enough.

    !=

    !=

    !=

    !=


  • ♿ (Parody)

    @Sutherlands said:

    !=

    !=

    !=

    !=

    Uh, that's not good enough in C, because:
    (1 != 2)  != (1 ^^ 2)
    
    You'd have to do:
    (!1 != !2)  == (1 ^^ 2)
    


  • @boomzilla said:

    @Sutherlands said:

    !=

    !=

    !=

    !=

    Uh, that's not good enough in C, because:
    (1 != 2)  != (1 ^^ 2)
    
    You'd have to do:
    (!1 != !2)  == (1 ^^ 2)
    

    != is not the same as ^^ because ^^ would do implicit casts to a pseudo-boolean type and != doesn't.  Gotcha.



  • @Sutherlands said:

    If you have trouble memorizing the precedence rules for any language, here is an easy pneumonic to remember them by:

     

    Multiply/Divide comes before Add/Subtract.

    Use parenthesis for everything else.

     

     

    First, that's not pneumonic at all, you probably meant mnemonic. Second, that's not a very good mnemonic device, it's just the thing you have to remember. For instance, the mnemonic they normally teach kids in school to remember this stuff is "PEMDAS left to right" for algebra - parentheses, exponents, multiplication/division, addition/subtraction from left to right. That's actually a mnemonic, and it applies just as much to programming languages as it does to algebra. The only difference is that most programming languages don't have arbitrary exponentiation as a built in operation.

    (and it also reminds me of a funny story - when I took a compilers class, some genius actually asked the TA "but how do we know which order we're supposed to execute arithmetic instructions in, after they've been parsed?" The TA was a little flabbergasted, since you would just use the normal order of operations, so he said "You just use bed mass!" Everyone gave him a WTF look. "You guys know what bed mass is, right? You know, basic algebra?" and he flipped out a little - how could junior and senior level CS students not know the basic order of algabraic operations? Turns out he was Canadian, and in Canadian schools they call parentheses "brackets" and use the mnemonic "BEDMAS", which none of us recognized)

     



  • @Tacroy said:

    Turns out he was Canadian, and in Canadian schools they call parentheses "brackets" and use the mnemonic "BEDMAS", which none of us recognized

    It was BODMAS when I went to school in the UK.

    SQL is another area where liberal use of parentheses really aids readability. Nothing worse that trying to wade through a bunch of ANDs and ORs to make sense of what is actually meant to be returned.


  • Garbage Person

    @Tacroy said:

    That's actually a mnemonic, and it applies just as much to programming languages as it does to algebra.
    Uh. I'm pretty damned sure that not 4 hours ago, I fixed a bug caused by C# deciding that a+b*c-d (okay, in reality it was WAY more complex than that) should be executed as read (or was it right-to-left?). A liberal sprinkling of parens fixed the problem.



  • @Weng said:

    @Tacroy said:

    That's actually a mnemonic, and it applies just as much to programming languages as it does to algebra.
    Uh. I'm pretty damned sure that not 4 hours ago, I fixed a bug caused by C# deciding that a+b*c-d (okay, in reality it was WAY more complex than that) should be executed as read (or was it right-to-left?). A liberal sprinkling of parens fixed the problem.

    Sounds like someone didn't RTFC#M.  Took me two seconds to google this:

    [quote user="The Old New Thing: What is the order of evaluation in C#?"]

    In the C# language, the order of evaluation is spelled out more explicitly. The order of evaluation for operators is left to right

    [/quote] Bear in mind that the order of evaluation of terms and subexpressions is entirely unrelated to the operator precedence used when combining the evaluated intermediate results of those terms and subexpressions into a final overall result.

     



  •  @Sutherlands said:

    != is not the same as ^^ because ...



  • @Tacroy said:

    @Sutherlands said:

    If you have trouble memorizing the precedence rules for any language, here is an easy pneumonic to remember them by:

     

    Multiply/Divide comes before Add/Subtract.

    Use parenthesis for everything else.

     

     

    First, that's not pneumonic at all, you probably meant mnemonic.

     

    Beat me to it.  How did that bit of confusion get started?  I've heard it more and more in the last few years.  My best guess is that somebody saw a (poor) phonetic spelling of "mnemonic," maybe written as "nuh-mon-ik" and thought that "nuh" should be pronounced "new."  I remember a similar thing happening in 6th grade, when some moron tried to convince me that the Greek queen of the gods was called "Heru" on the basis of a "hair-uh" phonetic spelling.

    Either that, or people were so traumatized by Johnny Mnemonic that they can no longer pronounce the word correctly.



  • @Faxmachinen said:

    I woke up this morning to realize that the presedence of the binary operators in C/C++ make no fucking sense.

    Whatever gets you up in the morning!

    (The funniest part of this thread is imagining Faxmachinen suddenly sitting bolt-upright in bed and screaming out "binary operators in C++ make no fucking sense!" Possibly waking a pet that was sleeping on his lap. That then goes running out of the room and knocks over a ladder that was placed over him with an open paint can and then the paint gets all over him. Ok none of this is funny, but whatever I'm still typing anyway.)



  • @blakeyrat said:

    Ok none of this is funny, but whatever I'm still typing anyway.

    Never stopped me before...



  • @Tacroy said:

    First, that's not pneumonic at all, you probably meant mnemonic.

    That'll teach me not to think as I type.

    @Tacroy said:

    Second, that's not a very good mnemonic device, it's just the thing you have to remember.

    That was intended (just wanted to call it that), although not obvious.

     

    @DaveK said:

    @Weng said:

    @Tacroy said:

    That's actually a mnemonic, and it applies just as much to programming languages as it does to algebra.
    Uh. I'm pretty damned sure that not 4 hours ago, I fixed a bug caused by C# deciding that a+b*c-d (okay, in reality it was WAY more complex than that) should be executed as read (or was it right-to-left?). A liberal sprinkling of parens fixed the problem.

    Sounds like someone didn't RTFC#M.  Took me two seconds to google this:

    [quote user="The Old New Thing: What is the order of evaluation in C#?"]

    In the C# language, the order of evaluation is spelled out more explicitly. The order of evaluation for operators is left to right

    Bear in mind that the order of evaluation of terms and subexpressions is entirely unrelated to the operator precedence used when combining the evaluated intermediate results of those terms and subexpressions into a final overall result.

    [/quote]

    I don't know what either of you are talking about.  a+b*c+d should be, and is, evaluated as a+(b*c)+d.  I'm assuming the problem was that you wanted the * to separate 2 parts of an expression?  This has nothing to do with operators



  • @toshir0 said:

    @Sutherlands said:
    != is not the same as ^^ because ...
    That took longer than I expected.

    @Sutherlands said:

    That'll teach me not to think as I type.
    Next time type before thinking.

    @Sutherlands said:

    That'll teach me not to think as I type.
    I believe you. This is something I can see myself doing.

    @Sutherlands said:

    This has nothing to do with operators
    Huh?

     



  • Well, not sure why you quoted the same part twice, but...

    @Zecc said:

    @Sutherlands said:
    This has nothing to do with operators
    Huh?

    Sorry, should say operands.  Operators are NOT evaluated left-to-right.  At least not all of them anyway, so if he was referring to operands, it has no bearing, and if he was referring to operators, he's wrong.


  • @Sutherlands said:

    Well, not sure why you quoted the same part twice, but...
    Copy+paste with missing replace. What I meant was:

    @Zecc said:

    @Sutherlands said:
    That was intended (just wanted to call it that), although not obvious.
    I believe you. This is something I can see myself doing.
    Though it also applies as I initially quoted. I usually preview before I post, but sometimes I feel lucky (and I nearly made the same mistake again btw).



  • In the C# language, the order of evaluation is spelled out more explicitly. The order of evaluation for operators is left to right

    Please learn to read and NOT misquote!

    Operands in an expression are evaluated from left to right. For example, in F(i) + G(i++) * H(i), method F is called using the old value of i, then method G is called with the old value of i, and, finally, method H is called with the new value of i. This is separate from and unrelated to operator precedence.

     "i" is consistently evaluated from left to right independent of the order in which the result of F(), G() and H() are combined [G() and H() are multiplied before being added to F()]

     This is in contrast to C/C++ where one must know where the "Sequence Points" are in order to dermine the value of a given element that changes during the evaluation of the expression and is used multiple times.



  • @PedanticCurmudgeon said:

    @Sutherlands said:

    If you have trouble memorizing the precedence rules for any language, here is an easy pneumonic to remember them by:

     

    Multiply/Divide comes before Add/Subtract.

    Use parenthesis for everything else.

     

    That's good advice even if you can remember the precedence rules.
    Oh i know all the operator precedence rules by hearth, and i loved to write code with as little parenthesis as possible.

    Now, just 2 years later, my preference is to leave no ambiguity anywhere, and wrap pieces of calculations in functions instead of warpping the functions inside the calculations.

     



  • @blakeyrat said:

    @Faxmachinen said:
    I woke up this morning to realize that the presedence of the binary operators in C/C++ make no fucking sense.

    Whatever gets you up in the morning!

    (The funniest part of this thread is imagining Faxmachinen suddenly sitting bolt-upright in bed and screaming out "binary operators in C++ make no fucking sense!" Possibly waking a pet that was sleeping on his lap. That then goes running out of the room and knocks over a ladder that was placed over him with an open paint can and then the paint gets all over him. Ok none of this is funny, but whatever I'm still typing anyway.)

     

    Or putting the whole experience into a Blues song....

    Woke up this morning
    Feelin' real tense
    Those C operators
    Make no fuckin' sense

     



  • @TheCPUWizard said:

    In the C# language, the order of evaluation is spelled out more explicitly. The order of evaluation for operators is left to right

    Please learn to read and NOT misquote!

    Please learn to click on the fucking link and see that I did not misquote Raymond Chen one little bit.




  • @Sutherlands said:

    @DaveK said:

    @Weng said:

    @Tacroy said:

    That's actually a mnemonic, and it applies just as much to programming languages as it does to algebra.
    Uh. I'm pretty damned sure that not 4 hours ago, I fixed a bug caused by C# deciding that a+b*c-d (okay, in reality it was WAY more complex than that) should be executed as read (or was it right-to-left?). A liberal sprinkling of parens fixed the problem.

    Sounds like someone didn't RTFC#M.  Took me two seconds to google this:

    [quote user="The Old New Thing: What is the order of evaluation in C#?"]

    In the C# language, the order of evaluation is spelled out more explicitly. The order of evaluation for operators is left to right

    Bear in mind that the order of evaluation of terms and subexpressions is entirely unrelated to the operator precedence used when combining the evaluated intermediate results of those terms and subexpressions into a final overall result.

    I don't know what either of you are talking about.  a+b*c+d should be, and is, evaluated as a+(b*c)+d.  I'm assuming the problem was that you wanted the * to separate 2 parts of an expression?  This has nothing to do with operators

    [/quote] Yes, there was a typo in Raymond Chen's article, it very obviously should have said "operands" rather than "operators", and indeed that is what you would have seen the C# spec actually says had you followed his link to the MSDN docs.  I actually looked right past it and just saw what he meant, as you can see from what I wrote; I did however think it was obvious that the phrase "terms and subexpressions" refers to operands, not operators.

    Besides, think about what you're saying.  Weng reported he had just fixed a bug related to order-of-evaluation in a C# program.  Are you saying that you really believed Weng's problem was caused because C# would evaluate "3 + 4 * 2" as 14?  I figured it was some problem with an assumption about what order functions f, g, and h would be called in an expression like "f() + g() * h()".  It seemed obvious to me that he could not have been talking about order of evaluation of operators, because C#  does not calculate "x + y * z" as "(x+y) * z", and we know that it does not, so I figured we can infer he must have been talking about a problem caused by the order of evaluation of operands, and the article I found - despite its typo - was talking about exactly that, and indeed if you read the article or the reference it linked to it would have been obvious that that was what it was actually talking about. 




  • What is the big deal with the order of evaluerenatiom of operands anyway? Do you functions have... eeeek.... side effects?



  • I did read it, tyvm.  I, however, did not assume that a bug in a+b*c+d had anything to do with functions.  A good reason to NOT assume that is because adding parenthesis fixed the problem.  Had it been related to operands, parenthesis would not have fixed it (although i could be wrong on this part).  Another reason to not assume that is because none of those are functions, and had the OP meant for them to be functions, he would have made them functions.  And obviously, since I wrote down what the correct order of precedence was, and the correct result, I thought that it had to do with simple arithmetic precedence.

    tl;dr - If you're going to make assumptions about what other people said, state your assumptions in your post.  Don't assume that everyone else made the same assumptions as you.


Log in to reply