Logical conditions in C ++

2

I have a question about the logic in the C ++ conditions. I have the following code:

if (distanciaCM<=50 && digitalRead(bombaPIN) == HIGH || f=="off"){
//mi código si se cumple la condición
}

Now, am I correct if I say that the code within the condition will be fulfilled if both conditions, the first and second are fulfilled or if the third one is fulfilled? In other words, will the code be executed in any of the 2 cases? Or are they 3 or just one?

    
asked by Juan Trinidad Mayo 22.01.2018 в 18:52
source

3 answers

5

You can translate

distanciaCM<=50 && digitalRead(bombaPIN) == HIGH || f=="off"

As a truth table

A = distanceCM

answered by 22.01.2018 / 19:10
source
4

As an addition to the excellent responses of Reynald0 and eferion I would like to comment on something that has been overlooked by both of you and that is relevant to your question.

Question.

  

Am I correct if I say that the code within the condition will be fulfilled if both conditions, the first and second are fulfilled or if the third one is fulfilled?

In Spanish, your code says the following:

if (distanciaCM<=50 && digitalRead(bombaPIN) == HIGH || f=="off"){
//mi código si se cumple la condición
}
  

If distanciaCM is less than or equal to 50 AND the return of digitalRead(bombaPIN) is HIGH , O if f is "off" then execute the code .

Lazy logic.

But in C ++ the sentence in the previous section is not exactly true; C ++ uses short circuit evaluation 1 which means that after evaluating the first operating from a logical statement we can ignore the second operand, this second operand will not be executed.

In which cases does C ++ short-circuit the evaluation?

  • When evaluating A && B if A is false , we know that the whole operation will be false regardless of the value of B so, B is not evaluated.
  • When evaluating A || B if A is true , we know that the whole operation will be true regardless of the value of B so, B is not evaluated.

Consequences for the code.

If any of the short-circuited operands is a function call, that function will not be called. In your case you have a function call on the short side ( digitalRead(bombaPIN) ) and that call will not occur if distanciaCM is less than or equal to 50 , on the other hand the comparison f=="off" will never occur again if distanciaCM is less than or equal to 50 and the return of digitalRead(bombaPIN) is HIGH , we can check it with this code:

enum e { HIGH, LOW };

bool digitalRead(bool b) {
    std::cout << __FUNCTION__ << '\n';
    return b ? HIGH : LOW;
}

struct F {
    bool operator ==(const char *tag) const {
        std::cout << __FUNCTION__ << '\n';
        return false;
    };
} f;

int main()
{
    for (int distanciaCM = 45; distanciaCM != 55; ++distanciaCM)
    {
        const bool bombaPIN = (distanciaCM % 2) == 0;

        std::cout << distanciaCM << '\n';
        if (distanciaCM<=50 && digitalRead(bombaPIN) == HIGH || f=="off"){
            std::cout << "mi código si se cumple la condición\n";
        }
    }

    return 0;
}

In the previous example we see how the digitalRead function has the secondary effect of showing its name in the console; we also see that the call to the equity operator of the object F does the same, this produces the following output:

45
digitalRead
operator==
46
digitalRead
mi código si se cumple la condición
47
digitalRead
operator==
48
digitalRead
mi código si se cumple la condición
49
digitalRead
operator==
50
digitalRead
mi código si se cumple la condición
51
operator==
52
operator==
53
operator==
54
operator==

We can see that while distanciaCM is less than or equal to 50 function digitalRead has been executed (it has been short-circuited). We can also see that when the first part of the expression was true the second part has not been executed either:

| distanciaCM | distanciaCM<=50 | digitalRead(bombaPIN) == HIGH |         f=="off" |
|          45 |       verdadero |                         falso |            falso |
|          46 |       verdadero |                     verdadero |    cortocircuito |
|          47 |       verdadero |                         falso |            falso |
|          48 |       verdadero |                     verdadero |    cortocircuito |
|          49 |       verdadero |                         falso |            falso |
|          50 |       verdadero |                     verdadero |    cortocircuito |
|          51 |           falso |                 cortocircuito |            falso |
|          52 |           falso |                 cortocircuito |            falso |
|          53 |           falso |                 cortocircuito |            falso |
|          54 |           falso |                 cortocircuito |            falso |

As you see, whenever distanciaCM<=50 was not fulfilled, the function digitalRead was not executed, we can also see that if distanciaCM<=50 && digitalRead(bombaPIN) == HIGH was true, it was not called the second part of the comparison.

Reorder conditions.

If you need the digitalRead function to be called you should always flip the expression:

//  vvvvvvvvvvvvvvvvvvvvvvvvvvvvv <--- siempre se ejecuta
if (digitalRead(bombaPIN) == HIGH && distanciaCM<=50 || f=="off"){
//        posible cortocircuito ---> ~~~~~~~~~~~~~~~
//mi código si se cumple la condición
}

Other things to consider.

Operators defined by the user (OdU) are not affected by the short circuit.

1 Also known as lazy logic.

    
answered by 23.01.2018 в 17:40
3

As there are no parentheses that group the expressions then the operators will be evaluated according to their order of precedence.

The operator && has more priority than the operator || then it will be evaluated in the first instance. Thus, the following expression would be equivalent:

if ((distanciaCM<=50 && digitalRead(bombaPIN) == HIGH) || f=="off")
//  ^                                                ^

Or, simplifying:

if ((A && B) || C)

The truth table is the one that has told you @ Reynald0 , so I see no need to repeat it .

    
answered by 22.01.2018 в 19:41