-
Logical And
Code:
#include <stdio.h>
int expr(char str[], int i){
printf("%s \n",str);
return i;
}
int main()
{
if(expr("1st",1) || expr("2nd",0) && expr("3rd",1));
return 0;
}
)
output
-------
1st
Logical and has Higher precedence then logical or
Then why the above code evaluated expr("1st",1) first
and not expr("2nd",0) && expr("3rd",1)
-
don't even worry about presidence, use parenthisies. :)
-
As it was explained to me the conditions are evaulted from left to right.
Also it would make more since to evaulte the left side of the || first since if it is true that would be all it needed to enter into the condition.
Code:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main (void)
{
int x, y=100, z;
const int range=20, cutoff=1;
srand ( (unsigned) time(NULL));
while ( ((x=rand()%range)!=0) && ( (z=(y/x)) > cutoff) )
{
printf("%d\t%d\n",x, z);
}
printf("%d\t%d\n", x, z);
return 0;
}
As you can see the right side of the && isn't even evaulated when x is zero since the program is able that the condition is false and can leave the loop.
And an example using your conditions while some modifications to the functions. (note: The added () around the && conditions do not change it, was just a warning the compiler gave)
Code:
#include <stdio.h>
int fun1 (char str[], int i)
{
printf("Evaluating %s condition. ", str);
if ( i == 1)
{
printf("Returning false.\n");
return 0;
}
else
{
printf("Returning true.\n");
return 1;
}
}
int fun2 (char str[], int i)
{
printf("Evaluating %s condition. ", str);
if ( i != 1)
{
printf("Returning false.\n");
return 0;
}
else
{
printf("Returning true.\n");
return 1;
}
}
int main (void)
{
printf("First one: \n");
if (fun1("1st",1) || (fun1("2nd",2) && fun1("3rd",3)) );
printf("Second one: \n");
if (fun2("1st",1) || (fun2("2nd",2) && fun2("3rd",3)) );
return 0;
}
-
Any good C book should explain the left-to-right evaluation of && and ||
In short
if ( a && b )
b is not evaluated if a is false. There would be no point to evaluating b because the expression would still be false
if ( a || b )
b is not evaluated if a is true. There would be no point to evaluating b because the expression would still be true
One thing it allows you to do for example is test a pointer and dereference it in the same expression
if ( p != NULL && *p != '\n' ) /* not the end of a valid string */
You can be sure that if p is NULL, then it won't be dereferenced to check for a newline character.
-
I am not wondering why the right hand side is not evaluated when the left hand side determines the outcome
I want to know why the AND is not evaluated first when it got higher precedence over OR as in a arithmetic operator * got higher precedence over +
5 + 2 * 3
2 * 3 is evaluated first not 5 + 2
then why in expression
expr("1st",1) || expr("2nd",0) && expr("3rd",1)
OR side is evaluated first
-
Where's the problem here?
Given expr("1st",1) || expr("2nd",0) && expr("3rd",1), you get
a is expr("1st",1)
b is expr("2nd",0) && expr("3rd",1)
So if a is true, b isn't evaluated
The precedence only tells you that you have
expr("1st",1) || ( expr("2nd",0) && expr("3rd",1) )
and not
( expr("1st",1) || expr("2nd",0) ) && expr("3rd",1)
http://www.eskimo.com/~scs/C-faq/q3.5.html
> as in a arithmetic operator * got higher precedence over +
Yeah, but you don't know which order the operands are evaluated in.
Given
f1() + f2() * f3()
There is nothing stopping the compiler from calling f1() first, saving the result for later and then calling f3() followed by f2(). For sure precedence tells you how the results are combined, but it does nothing to tell you in which order the individual sub-expressions are evaluated in.
If in some horrible code, the outcome of f2() depended on whether f1() was called first, then you'd be in for a lot of grief at some point.
http://www.eskimo.com/~scs/C-faq/q3.4.html
The important point for the boolean operators is that the left-to-right order is guaranteed.
Consider again my
if ( p != NULL && *p != '\n' )
If the order were not always predictably left-to-right, then it would randomly crash with a segmentation fault at the whim of the implementation of the compiler, because it dereferenced a pointer before checking that it was NULL.
Then you would be in the sorry mess that Pascal is in, where you have to implement && and || using if / else chains if one part of the expression guards the evaluation of another part of the expression.
http://www.lysator.liu.se/c/bwk-on-pascal.html
Yes Pascal has 'and' and 'or', but they don't have useful left-to-right properties.
-
Salem I respect you but you are wrong on the Pascal point. The paper you linked is from 1981. The standard for Pascal has had some improvements done. As such modern compilers (such as Free Pascal) use the C style method of left to right evaluation and stopping as soon as it has enough to determine if it should go into the condition or not.
I read BWK's paper and I am sure its 100% accurate for 1981 but it is not for 2004.