2013-11-18 2 views
5

Is a && b && c, определяемый по языку (a && b) && c или a && (b && c)?Имеют ли бинарные логические операторы ассоциативность?

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

+4

Да, это важно. Короткое замыкание предотвратит оценку некоторых ваших операндов. – meagar

+0

@meagar Как бы '(a && b) && c' отличаться от' a && (b && c) 'относительно короткого замыкания? Например, как бы '(false && b) && c' отличаться от' false && (b && c) '? Оба выражения не оценивают ни 'b', ни' c' ... – fredoverflow

+1

@FredOverflow, если 'a' является ложным, вы правы. если 'b' является ложным,' c' никогда не оценивается. В принципе, если есть некоторая «ложная» слева от некоторых условий AND'd, тесты останавливаются на ней. –

ответ

10

§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 

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

+0

Я считаю, что все бинарные операторы эквивалентного приоритета следуют этому соглашению. –

+0

Чтобы быть ясным, это означает '(a && b) && c', а не' a && (b && c) ', правильно? – fredoverflow

+1

@ZacHowland: условные операторы и присваивание (чтобы назвать только два, о которых я могу думать сразу), группу справа налево, поэтому 'a = b = c' эквивалентно' a = (b = c) '. –

5

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

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

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

+0

@FredOverflow прямо у вас есть. Я добавил способ более практичный и на самом деле обычный случай. –

+0

Если вы добавляете явные скобки для изменения ассоциативности выражения, то есть 'if (! A.empty() && (! A [0] .empty() && a [0] .back() == 3))' -- Есть ли разница? Я не думаю, что это так. –

+0

@BenjaminLindley нет. Я считаю, что мой ответ касается более ранней версии вопроса, где, если выражение оценивается слева направо или справа налево, было включено –

5

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

Следовательно, математик будет описывать их как лево-ассоциативные, например.
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, в котором, по крайней мере, в некоторых случаях заключенные в скобки выражения должны оцениваться в первую очередь.

+0

Итак, конечный результат заключается в том, что это не имеет значения, правильно? – fredoverflow

+0

Er, если по значению "это не имеет значения" вы имеете в виду, что '' a && b && c' оценивается строго слева направо, независимо от их скобки ", то да. См. Править. – zwol

2

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

Ассоциативных недвижимости

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

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

+0

Как бы '(false && b) && c' отличаться от' false && (b && c) '? Оба выражения не оценивают ни 'b', ни' c' ... – fredoverflow

+0

В этом случае вы правы.Логический поток - это просто слева направо, поэтому, когда вы достигаете своего первого «ложного» состояния в цепочке условий, он останавливается там. Поскольку '&&' является ассоциативным по своей природе, пока вы не бросаете '||' там, это не будет иметь большого значения. Как только у вас есть условие '||', скобки начинают иметь значение. –

 Смежные вопросы

  • Нет связанных вопросов^_^