Clueless
Clueless

Reputation: 15

C++ ordering of || and && when testing eqaulity in if statement

This is a really simple one, that I can't find an answer for.

I'm trying to write function that returns a bool when passed two chars of which the left has higher precedence.

I can achieve the required functionality with the following:

bool Precedence(char lhs, char rhs) {
  if ((lhs == '*' || lhs == '/') && (rhs == '+' || rhs == '-'))
    return true;
  return false;
}

which is fine and dandy but why how isn't the following exactly the same:

bool Precedence(char lhs, char rhs) {
  if ((lhs == ('*' || '/')) && (rhs == ('+' || '-')))
    return true;
  return false;
}

I know it is wrong, but why? To me they both read indentically. Sorry I know this is stupid but it's driving me mad.

Upvotes: 0

Views: 161

Answers (6)

Sam Estep
Sam Estep

Reputation: 13354

In C++, the || and && operators treat their operands as boolean values. In other words, you'll get unexpected results if you use anything but boolean values as operands for either of those operators. Think of it this way: if you were to evaluate this expression:

(lhs == ('*' || '/')) && (rhs == ('+' || '-'))

what would you get? Let's go through it the way C++ would. First, you need to evaluate within parentheses, so we need to evaluate these two expressions:

'*' || '/'
'+' || '-'

What do these expressions mean? They don't really make much logical sense. You can't ask "Is lhs equal to '*' or '/'?" because there is no notion of "'*' or '/'" in C++, at least not in the sense you're probably thinking.

When you ask C++ whether the expression '*' || '/' is true, it simply converts both characters to their bit representations and determines whether those bit representations contain any 1's. Since neither '*' nor '/' is the null character, both contain 1's in their binary representations, so the expression always evaluates to true.

Upvotes: 0

Loduwijk
Loduwijk

Reputation: 1977

In the correct version, you are checking first to see if (lhs == '*'), which evaluates to either true or false. The other similar comparisons likewise evaluate to true or false. Then your || and && operators compare true/false values.

If you do ('' || '+') you are not comparing true/false values, though since C/C++ are very flexible when it comes to using data in ways it may not have been intended, it is still using the data for '' and for '+' as if they were true/false values. In C and C++, 0 (and other values that are represented by a 0 or leading 0 such as null, false, "") are false, and other values are true, so '*' is a true value.

So doing (character || character) (where neither character is a null character) is like doing (true || true), which will always evaluate to true no matter which character you use. So you are basically doing lhs == (true || true) which again is the same as lhs==true. So you are just checking to see if lhs is true.

Upvotes: 0

TartanLlama
TartanLlama

Reputation: 65720

C++ doesn't define logical operators like that.

lhs == ('*' || '/') does not mean lhs equals * or /, it returns true if lhs is 1.

The ('*' || '/') subexpression evaluates to true unconditionally, because boolean logic on chars is analogous to checking if they are 0 or not. Now your expression looks like lhs == true, or lhs == 1.

Upvotes: 5

Bathsheba
Bathsheba

Reputation: 234825

'*' is a char literal with non-zero value. '/' similarly.

'*' || '/' is therefore non-zero, and not likely to equal lhs. In fact, due to short-circutting of ||, '/' will not be evaluated.

So (lhs == ('*' || '/')) && (rhs == ('+' || '-')) is very different to ((lhs == '*' || lhs == '/') && (rhs == '+' || rhs == '-')).

Upvotes: 1

bznein
bznein

Reputation: 908

The meaning of (lhs == ('*' || '/')) (and the equivalent one with rhs) it's not what you may think in an intuitive way.

What happens is the following:

The part between the parenthesis gets evaluated: ('*' || '/') is a boolean condition which evaluates to true (since at least one of the two char -in this case both- it's not 0). Then the lhs==true gets evaluated, which has not the meaning that you want it to have.

The same holds for (rhs == ('+' || '-'))

Upvotes: 4

yizzlez
yizzlez

Reputation: 8805

('*' || '/') and ('+' || '-') always return true because they are non-zero char values, which is why the following code doesn't work.

Upvotes: 1

Related Questions