Является a && b && c
определяется языком, чтобы означать (a && b) && c
или же a && (b && c)
?
Вау, Джерри был быстр. Чтобы усилить вопрос: действительно ли это имеет значение? Будет ли заметная разница между a && b && c
интерпретируется как (a && b) && c
или же a && (b && c)
?
§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
Предостережение: это только показывает, как это Можно быть сделан, чтобы иметь значение. я не особенно рекомендую, чтобы кто-нибудь сделал это, только показывая, что, если вы хотите достаточно сильно, вы можете создать ситуацию, в которой это будет иметь значение.
&&
а также ||
операторы короткого замыкания: если операнд слева определяет результат общего выражения, операнд справа даже не будет оцениваться.
Следовательно, математик описал бы их как левоассоциативные, например,
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, где по крайней мере в некоторых случаях выражения в скобках должны быть оценены сначала.
На самом деле очень важно, чтобы выражение вычислялось слева направо. Это используется для короткого замыкания в некоторых выражениях. Вот случай, когда это имеет значение:
vector<vector<int> > a;
if (!a.empty() && !a[0].empty() && a[0].back() == 3)
Могу поспорить, что вы пишете подобные заявления несколько раз в день. И если бы ассоциативность не была определена, у вас были бы огромные проблемы.
Если a && b
ложно, то && c
порция никогда не проверяется. Так что да, это имеет значение (по крайней мере, потому, что вам нужно, чтобы ваши операции были упорядочены слева направо). &&
это ассоциативная операция по своей природе.
Ассоциативная собственность
В выражении, содержащем два или более вхождения в строке
тот же ассоциативный оператор, порядок, в котором операции
выполняется не имеет значения, пока последовательность операндов
не изменилось. То есть перестановка скобок в такой
выражение не изменит свое значение.
Так что не имеет значения (логически), если вы напишите это как a && (b && c)
или же (a && b) && c
, Оба эквивалентны. Но вы не можете изменить порядок операций (например, a && c && b
не эквивалентно a && b && c
).