Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do the binary boolean operators have associativity?

Is a && b && c defined by the language to mean (a && b) && c or a && (b && c)?

Wow, Jerry was quick. To beef up the question: does it actually matter? Would there be an observable difference between a && b && c being interpreted as (a && b) && c or a && (b && c)?

like image 557
fredoverflow Avatar asked Nov 18 '13 16:11

fredoverflow


People also ask

Are Boolean operations associative?

∀a,b,c∈S:(a∨b)∨c=a∨(b∨c) That is, both ∨ and ∧ are associative operations.

Is Boolean logic associative?

The basic Laws of Boolean Algebra that relate to the Commutative Law allowing a change in position for addition and multiplication, the Associative Law allowing the removal of brackets for addition and multiplication, as well as the Distributive Law allowing the factoring of an expression, are the same as in ordinary ...

Which operator has right associativity?

The right-associativity of the = operator allows expressions such as a = b = c to be interpreted as a = (b = c) .

What are associativity of operators are logical operators associative?

Operators Associativity is used when two operators of same precedence appear in an expression. Associativity can be either Left to Right or Right to Left. For example: '*' and '/' have same precedence and their associativity is Left to Right, so the expression “100 / 10 * 10” is treated as “(100 / 10) * 10”.


2 Answers

§5.14/1: "The && operator groups left-to-right. [...] Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false."

As to when or how it matters: I'm not sure it really does for built-in types. It's possible, however, to overload it in a way that would make it matter. For example:

#include <iostream>

class A;

class M {
    int x;
public:
    M(int x) : x(x) {}
    M &operator&&(M const &r); 
    M &operator&&(A const &r); 
    friend class A;
};

class A {
    int x;
    public:
    A(int x) : x(x) {}
    A &operator&&(M const &r); 
    A &operator&&(A const &r);
    operator int() { return x;}
    friend class M;
};

M & M::operator&&(M const &r) {
    x *= r.x;
    return *this;
}

M & M::operator&&(A const &r) {
    x *= r.x;
    return *this;
}

A &A::operator&&(M const &r) {
    x += r.x;
    return *this;
}

A &A::operator&&(A const &r) {
    x += r.x;
    return *this;
}

int main() {
    A a(2), b(3);
    M c(4);

    std::cout << ((a && b) && c) << "\n";
    std::cout << (a && (b && c)) << "\n";
}

Result:

9
16

Caveat: this only shows how it can be made to matter. I'm not particularly recommending that anybody do so, only showing that if you want to badly enough, you can create a situation in which it makes a difference.

like image 79
Jerry Coffin Avatar answered Nov 01 '22 10:11

Jerry Coffin


The && and || operators short-circuit: if the operand on the left determines the result of the overall expression, the operand on the right will not even be evaluated.

Therefore, a mathematician would describe them as left-associative, e.g.
a && b && c(a && b) && c, because to a mathematician that means a and b are considered first. For pedagogical purposes, though, it might be useful to write a && (b && c) instead, to emphasize that neither b nor c will be evaluated if a is false.

Parentheses in C only change evaluation order when they override precedence. Both a && (b && c)
and (a && b) && c will be evaluated as a first, then b, then c. Similarly, the evaluation order of both
a + (b + c) and (a + b) + c is unspecified. Contrast a + (b * c) versus (a + b) * c, where the compiler is still free to evaluate a, b, and c in any order, but the parentheses determine whether the multiplication or the addition happens first. Also contrast FORTRAN, where in at least some cases parenthesized expressions must be evaluated first.

like image 5
zwol Avatar answered Nov 01 '22 10:11

zwol