Есть ли у бинарных булевых операторов ассоциативность?

Является a && b && c определяется языком, чтобы означать (a && b) && c или же a && (b && c)?

Вау, Джерри был быстр. Чтобы усилить вопрос: действительно ли это имеет значение? Будет ли заметная разница между a && b && c интерпретируется как (a && b) && c или же a && (b && c)?

5

Решение

§5.14 / 1: « && оператор группы слева направо. […] В отличие от &, && гарантирует слева направо
оценка: второй операнд не оценивается, если первый операнд является ложным. «

Что касается того, когда или как это имеет значение: я не уверен, что это действительно имеет значение для встроенных типов. Однако возможно перегрузить его так, чтобы это имело значение. Например:

#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";
}

Результат:

9
16

Предостережение: это только показывает, как это Можно быть сделан, чтобы иметь значение. я не особенно рекомендую, чтобы кто-нибудь сделал это, только показывая, что, если вы хотите достаточно сильно, вы можете создать ситуацию, в которой это будет иметь значение.

10

Другие решения

&& а также || операторы короткого замыкания: если операнд слева определяет результат общего выражения, операнд справа даже не будет оцениваться.

Следовательно, математик описал бы их как левоассоциативные, например,
a && b && c(a && b) && cпотому что для математика это означает a а также b считаются первыми. Однако в педагогических целях было бы полезно написать a && (b && c) вместо этого, чтобы подчеркнуть, что ни b ни c будет оцениваться, если a ложно

Скобки в C изменяют порядок оценки только при переопределении старшинство. И то и другое a && (b && c)
а также (a && b) && c будет оцениваться как a будет первый b, затем c, Аналогично, порядок оценки обоих
a + (b + c) а также (a + b) + c не указано контрастировать a + (b * c) против (a + b) * cгде компилятор еще свободен для оценки a, b, а также c в любом порядке, но скобки определяют, происходит ли сначала умножение или сложение. Также противопоставьте FORTRAN, где по крайней мере в некоторых случаях выражения в скобках должны быть оценены сначала.

5

На самом деле очень важно, чтобы выражение вычислялось слева направо. Это используется для короткого замыкания в некоторых выражениях. Вот случай, когда это имеет значение:

vector<vector<int> > a;
if (!a.empty()  && !a[0].empty() && a[0].back() == 3)

Могу поспорить, что вы пишете подобные заявления несколько раз в день. И если бы ассоциативность не была определена, у вас были бы огромные проблемы.

5

Если a && b ложно, то && c порция никогда не проверяется. Так что да, это имеет значение (по крайней мере, потому, что вам нужно, чтобы ваши операции были упорядочены слева направо). && это ассоциативная операция по своей природе.

Ассоциативная собственность

В выражении, содержащем два или более вхождения в строке
тот же ассоциативный оператор, порядок, в котором операции
выполняется не имеет значения, пока последовательность операндов
не изменилось. То есть перестановка скобок в такой
выражение не изменит свое значение.

Так что не имеет значения (логически), если вы напишите это как a && (b && c) или же (a && b) && c, Оба эквивалентны. Но вы не можете изменить порядок операций (например, a && c && b не эквивалентно a && b && c).

2