How does Lua check conditions in an IF statement? - if-statement

I am trying to optimize my IF statement in Lua. When there are two conditions in an IF statement with the AND operator, does Lua read left to right and stop as soon as it reaches one false? That is, if there is a condition which is quick to check and a condition which is slower to check, is it more efficient to put the condition which is quick to check first (i.e. left most)?
For example, assume I have two functions that return true or false, quick_fn() and slow_fn(), and I want to execute code only if both functions return true. In terms of speed, is there a difference between the following two ways of writing this code? If Option #1 is equivalent, should I always be putting the quick_fn() in the leftmost spot?
Option #1:
if quick_fn() AND slow_fn() then
[code]
end
Option #2:
if quick_fn() then
if slow_fun() then
[code]
end
end

This is explained in the Lua documentation (emphasis added):
The negation operator not always returns false or true. The
conjunction operator and returns its first argument if this value is
false or nil; otherwise, and returns its second argument. The
disjunction operator or returns its first argument if this value is
different from nil and false; otherwise, or returns its second
argument. Both and and or use short-circuit evaluation; that is, the
second operand is evaluated only if necessary.
Note that the operator is spelled and, not AND. Lua is case-sensitive.

Related

Checking null pointer && pointer->member value in the same if statement

This is a pretty basic question, but I could not find a clear answer:
is it allowed to check that a pointer is not null and (&&) to also check one of its members value in the same if statement?
Rephrased: is the right part of the condition in the example below even evaluated if f is null?
I know this works in VS current version, but what I need to know is if this is allowed by the C++ standard (or if it's UB).
Also, if I write it as 2 separate if to make it more readable, can I expect the compiler to optimize it into a single if?
struct foo
{
bool bar;
};
void main(){
foo *f;
// DO THINGS
if (f != null && f->bar == true)
{
// DO THINGS
}
}
Edit: the question is different from this one because it's not obvious that it's simply a matter of order: the proof is I did not end on that SO answer when I googled my question.
...is it allowed to check that a pointer is not null and (&&) to also check one of its members value in the same if statement?
It's perfectly valid, it is not UB, the expression is evaluated from left to right, if the left part of the expression evaluates to false the right part is not evaluated. This is usually called operator short circuit.
The rationale is that if the first part is false, there is no possibilty of the whole expression being true, false && false is false, false && true is also false.
...if I write it as 2 separate if to make it more readable, can I expect the compiler to optimize it into a single if?
In light of the above answer, you wouldn't need two ifs, I would argue that it will not make your code more readable, I prefer the way you have it right know, in any case this is only my opinion. About the compiler, I wouldn't think that there will be much difference either way, as sampled in this live demo.
is it allowed to check that a pointer is not null and (&&) to also check one of its members value in the same if statement?
Yes.
is the right part of the condition in the example below even evaluated if f is null?
No.
what I need to know is if this is allowed by the C++ standard
Yes.
(or if it's UB)
No.
Also, if I write it as 2 separate if to make it more readable, can I expect the compiler to optimize it into a single if?
I would expect it. Seems like a trivial optimisation. Note that in cases where the && operator is overloaded (which never is in the case of pointers), such change can change the meaning of the program.
Standard quote (latest draft):
[expr.log.and]
The && operator groups left-to-right.
The operands are both contextually converted to bool.
The result is true if both operands are true and false otherwise.
Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.

Evaluating order 'and' for C++ in relation with null pointers

Please consider the following block of C++-code.
call * pCall; // Make a pointer to private variable call.
pCall = NULL; // We are sure that it is a null pointer.
aMemberFuntionThatMayChangeTheValueOfpCall();
if (pCall != NULL and pCall->isDelivered() == false){
doSomething();
}
I would like to execute some lines of code, here represented by doSomething(), if and only if pCall is not a null pointer and pCall->isDelivered() is false.
However, I read that the order of evaluation is unspecified. So theoretically the compiler may evaluate pCall->isDelivered() first, and run into a run time exception. However, in the debugging sessions it seems to evaluate the and-operator left to right. Can someone please shine a light on this? I don't want any failures of the code when it gets into a production environment or when it gets executed on another machine.
Of course it is possible to make it into two nested if-statements, but this makes the source far more unreadable because I need this kind of code multiple times.
Can anyone tell me how to do this evaluation in one if-statement such that there is no misevaluation?
Your and operator is more commonly written in C++ as &&, but they are both the same "logical and" operator. For this operator the order of evaluation is specified and evaluation is executed from left to right, guaranteed. (Otherwise millions of existing programs would fail).
The exception - not applicable to your code - is when the && operator is overloaded. In this case the left-to-right rule does not work. BTW it is a main reason why it is recommended not to overload this operator.
Your code below will work (I've changed 'and' to '&&' and added parentheses):
if ( (pCall != NULL) && (pCall->isDelivered() == false) ) {
doSomething();
}
because the logical-AND && will 'short circuit'; i.e. if the first expression is false, the second will not be evaluated. Evaluation order is from left to right in this case.
The following relates to the Miscosoft C++ compiler in VS2013:
Logical operators also guarantee evaluation of their operands from
left to right. However, they evaluate the smallest number of operands
needed to determine the result of the expression. This is called
"short-circuit" evaluation. Thus, some operands of the expression may
not be evaluated. For example, in the expression x && y++ the second
operand, y++, is evaluated only if x is true (nonzero). Thus, y is not
incremented if x is false (0).

C++ ternary operator execution conditions

I am unsure about the guarantees of execution for the C / C++ ternary operator.
For instance if I am given an address and a boolean that tells if that address is good for reading I can easily avoid bad reads using if/else:
int foo(const bool addressGood, const int* ptr) {
if (addressGood) { return ptr[0]; }
else { return 0; }
}
However can a ternary operator (?:) guarantee that ptr won't be accessed unless addressGood is true? Or could an optimizing compiler generate code that accesses ptr in any case (possibly crashing the program), stores the value in an intermediate register and use conditional assignment to implement the ternary operator?
int foo(const bool addressGood, const int* ptr) {
// Not sure about ptr access conditions here.
return (addressGood) ? ptr[0] : 0;
}
Thanks.
Yes, the standard guarantees that ptr is only accessed if addressGood is true. See this answer on the subject, which quotes the standard:
Conditional expressions group right-to-left. The first expression is contextually converted to bool (Clause 4). It is evaluated and if it is true, the result of the conditional expression is the value of the second expression, otherwise that of the third expression. Only one of the second and third expressions is evaluated. Every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second or third expression.
(C++11 standard, paragraph 5.16/1)
I would say, in addition to the answer that "yes, it's guaranteed by the C++ standard":
Please use the first form. It's MUCH clearer what you are trying to achieve.
I can almost guarantee that any sane compiler (with minimal amount of optimisation) generates exactly the same code for both examples anyway.
So whilst it's useful to know that both of these forms achieve the same "protection", it is definitely preferred to use the form that is most readable.
It also means you don't need to write a comment explaining that it is safe because of paragraph such and such in the C++ standard, thus making both take up the same amount of code-space - because if you didn't know it before, then you can rely on someone else ALSO not knowing that this is safe, and then spending the next half hour finding the answer via google, and either running into this thread, or asking the question again!
The conditional (ternary) operator guarantees to only evaluate the second operand if the first operand compares unequal to 0, and only evaluate the third operand if the first operand compares equal to 0. This means that your code is safe.
There is also a sequence point after the evaluation of the first operand.
By the way, you don't need the parantheses - addressGood ? ptr[0] : 0 is fine too.
c++11/[expr.cond]/1
Conditional expressions group right-to-left. The first expression is
contextually converted to bool (Clause 4).
It is evaluated and if it is true, the result of the conditional expression is the value of the second expression,
otherwise that of the third expression. Only one of the second and third expressions is evaluated. Every value
computation and side effect associated with the first expression is sequenced before every value computation
and side effect associated with the second or third expression.

C++ evaluates underlying if condition in a while statement

I have a problem that when c++ evaluates the while statement, it also evaluates the underlying if statement even if the while statement condition is not met.
ite_candidats is a custom iterator on a binary map tree. When there is no more nodes to visit, ite_candidat evaluates to NULL. So the while ends. But, I get a assertion failure from ite_candidats.clecourante() call, saying my underlying node is NULL. It shouldn't evaluate ite_candidats.clecourante() because it wasn't meant to get to it.
I ran the program in debug mode, and !!ite_candidats really evaluates to false when there is no more nodes to visit. If I comment out the if block, the program gets out of the while loop and everything is ok...
The operator overloading of ite_candidats operator bool() doesn't call clecourante().
while(!!ite_candidats){
if(ite_candidats.clecourante() != nompersonne){
{...}
}
ite_candidats++;
}
It is impossible. If it evaluates if then it enters into while. No ahead computation is C++.
P.S. Why do you have two negations in while?
rough guess: ite_candidats is incremented in the code. probably the end iterator is not evaluating to 0.
ite_candidats is a custom iterator on a binary map tree. When there is no more nodes to visit, ite_candidat evaluates to NULL.
Does it really evaluate to NULL? That's a bit dubious since you are using the dot operator rather than the dereference operator in ite_candidats.clecourante(). From the code that you did post, it looks like ite_candidats is an instance of some object rather than a pointer to some object.
The operator overloading of ite_candidats operator bool()
This, I suspect, is the problem. Your !!ite_candidats is going use that conversion operator to cast ite_candidats to a bool, negate that result to yield !ite_candidats, then negate again to yield !!ite_candidats.
The problem is that your operator bool() is checking for a condition different from the preconditions of WhatEverYourCustomIteratorClassIsNamed::clecourante().

Comma operator in a conditional

I have read in a lot of places but I really can't understand the specified behavior in conditionals.
I understand that in assignments it evaluates the first operand, discards the result, then evaluates the second operand.
But for this code, what it supposed to do?
CPartFile* partfile = (CPartFile*)lParam;
ASSERT( partfile != NULL );
bool bDeleted = false;
if (partfile,bDeleted)
partfile->PerformFileCompleteEnd(wParam);
The partfile in the IF was an unnecessary argument, or it have any meaning?
In this case, it is an unnecessary expression, and can be deleted without changing the meaning of the code.
The comma operator performs the expression of the first item, discards the results, then evaluates the result as the last expression.
So partfile,bDeleted would evaulate whatever partfile would, discard that result, then evaluate and return bDeleted
It's useful if you need to evaluate something which has a side-effect (for example, calling a method). In this case, though, it's useless.
For more information, see Wikipedia: Comma operator
bool bDeleted = false;
if (partfile,bDeleted)
partfile->PerformFileCompleteEnd(wParam);
Here, the if statement evaluates partfile,bDeleted, but bDelete is always false, so the expression fails to run. The key question is "what's that all about?". The probable answer is that someone temporarily wanted to prevent the partfile->PerformFileCompleteEnd(wParam); statement from running, perhaps because it was causing some problem or they wanted to ensure later code reported errors properly if that step wasn't performed. So that they're remember how the code used to be, they left the old "if (partfile)" logic there, but added a hardcoded bDeleted variable to document that the partfile->Perform... logic had effectively been "deleted" from the program.
A better way to temporarily disable such code is probably...
#if 0
if (partfile)
partfile->PerformFileCompleteEnd(wParam);
#endif
...though sometimes I try to document the reasoning too...
#ifndef DONT_BYPASS_FILE_COMPLETE_PROCESSING_DURING_DEBUGGING
if (partfile)
partfile->PerformFileCompleteEnd(wParam);
#endif
...or...
if (partFile, !"FIXME remove this after debugging")
partfile->PerformFileCompleteEnd(wParam);
The best choice depends on your tool set and existing habits (e.g. some editors highlight "FIXME" and "TODO" in reverse video so it's hard to miss or grey out #if 0 blocks; you might have particular strings your source-control checkin warns about; preprocessor defines only in debug vs release builds can prevent accidental distribution etc.).
partfile is evaluated, then bDeleted is evaluated and used as the test. Since evaluation of partfile does not have any side effects, removing it from the conditional has no effect.
The comma operator is a rather obscure feature of C/C++. It should not be confused with the comma in initialising lists (ie: int x, int y; ) nor with function call parameter separation comma (ie: func(x, y) ).
The comma operator has one single purpose: to give the programmer a guaranteed order of evaluation of an expression. For almost every operator in C/C++, the order of evaluation of expressions is undefined. If I write
result = x + y;
where x and y are subexpressions, then either x or y can be evaluated first. I cannot know which, it's up to the compiler. If you however write
result = x, y;
the order of evaluation is guaranteed by the standard: left first.
Of course, the uses of this in real world applications are quite limited...