Why is this output of this basic C program? - c

Let me be judged as a Noob in programming, I have been learning obfuscated way of programming in c/c++, as the c compiler compiles a statement from the right hand side towards the left hand side.
I have the following code:
int main(){
int x=5, y=20, z=1;
int k = x > y < z;
printf("%d", k);
return 0;
}
The output returned is 1, Does this means that
x > y < z = (x>y) < z
or
x > y < z = x > (y<z)
I would love if someone would give me link to work on these skills.
Thanks and Regards.

Change z=-1 or x=0 and find out. Also change int main() to the more correct int main ( void )
Changing z = -1 will ouput 0, whereas k will be 1 if you assign it x > y == z if z = 0. So in short:
k = x > y < z;
is the same as writing
k = (x > y) < z;
left-to-right.

According to the C grammar (6.5.8 Relational operators)
1 relational-expression:
shift-expression
relational-expression < shift-expression
relational-expression > shift-expression
relational-expression <= shift-expression
relational-expression >= shift-expression
1 The relational operators group left-to-right (C++ Standard :) )
And
6 Each of the operators < (less than), > (greater than), <= (less than
or equal to), and >= (greater than or equal to) shall yield 1 if the
specified relation is true and 0 if it is false.107) The result has
type int.
Thus the initializer in this declaration
int k =x>y<z;
is equivalent to
int k = ( x > y ) < z;
As x is less than y then expression x > y yields 0 and as z is greater than 0 then the full expression yields 1.
The following operators have right-to-left-grouping:
unary operators
conditional operator
assignmnet and compound assignment operators

First you have to check operator precedence, which is easiest by looking at an operator precedence table. If such a table is decent, it will list the operators > and < in a group called relational operators. All operators in this group have the same operator precedence.
Since the operators > and < have the same precedence, the order in which the operands will get processed is determined by the associativity of that group of operators. For the relational operators, this is left-to-right. Therefore the expression is guaranteed to be processed as (x > y) < z

In C the boolean values are numerical values, so:
false -> 0
true -> != 0, hence any number that is not 0 will represent the boolean true.
So in case of your code:
int k = x > y < z;
can be split in the following way:
int k = (x > y) < z;
that will be:
int k = ( 5 > 20) < 1;
the first part evaluates to false (0 that is) then the equality will loook this way:
int k = 0 < 1;
which is true, hence
int k = 1;

k = ( 5 > 20 ) < 1= False (0)
k = (0 < 1) = True (1)
printf (%d, k) = 1

Maybe you should know the Operator precedence and associativity. You can google or see the book <<c++ primer>>. First the operator > and < have a same precedence. Then we should use the associativity, there the operator only have left associativity. So the answer is x> y< z= (x>y)<z). I hope this can help you. Remember: 1. precedence; 2. associativity.

Related

Comparing three integer variables in one if condition (C) [duplicate]

This question already has answers here:
Why is a condition like (0 < a < 5) always true?
(4 answers)
Closed 9 years ago.
I have this question & in the answer it says that due to left to right associativity the result would be 1 that is true for this statement. This is the code.
#include<stdio.h>
int main ()
{
int i=0,x=10,y=10,z=5;
i=x<y<z;
printf("\n\n%d",i);
return 0;
}
But x is greater than z here so how is this happening ?
The expression x
(x < y) < z
so it becomes
(10 < 10) < 5
which further is evaluated into
0 < 5
which is true.
I think you wanted something like this:
x < y && y < z
Because of operator precedence and associativity
i = x < y < z;
is parsed as:
i = ((x < y) < z);
After substituting the variable values, this becomes:
i = ((10 < 10) < 5);
Since 10 < 10 is false, this becomes:
i = (0 < 5);
Since 0 < 5 is true, that becomes:
i = 1;
x<y<z is not a single valid expression. Instead it evaluates x<y first (operator precedence is done left to right here) as true/false (false in this case as they're equal), converts it to an int value of 0, and then compares this value with z.
Use (x < y && y < z) instead.
It first evaluates x < y which is false (0), then 0 < z which is true (1).
WHat C compiler does is, in x<y<z;
starts from left, so as x is not less than y therefore it replaces that expression with '0'
so it becomes 0<z and as that is true. it set the variable to 1.

Problems containing multiple "or" operators in C

I was solving some problems related to "or" operators in C.
The body of the program was like what mentioned below:
#include<stdio.h>
main() {
int i = 4, j = -1, k = 0, w, x, y, z;
w = i || j || k ;
x = i && j && k ;
z = i && j || k ;
printf("\n w=%d , x = %d", w, x);
printf("\n y=%d , z = %d", y, z);
}
Can someone please tell me the mechanism of these statements?
These are binary operators, they take two arguments. When confronted with a more complicated expression you can break it down into sets of binary operations.
For example, z = i && j || k; could be written as z = ( (i && j) || k ). Or in pictorial form:
z
=
||
/ \
&& k
/ \
i j
To know that the tree has this layout we look up operator precedence (or language grammar rules), the rule is that to choose between && and ||, the || is the 'outer' operation (i.e. lower precedence).
These operators also do short-circuiting, although that is not relevant in this particular example.
So, looking at the above table, i && j gives 1 because both i and j are non-zero. The 1 || k gives 1 because at least one of the operands is non-zero. Finaly 1 is assigned to z.
You can find the right values for w and x in a similar way, using the precedence rule that the left-most && is the inner one, when the situation is a && b && c, and similarly for ||.
the || and && operators are logical operators, which means they evaluate the numbers as either 'true' or 'false'
In that sense, i and j are 'true' and k is 'false'. So, calculating the outcome:
w = 'true' or 'true' or 'false' = true = 1
x = 'true' and 'true' and 'false' = false = 0
z = 'true' and 'true' or 'false' = true = 1
y isn't defined and will contain 0 or garbage
--edit--
note that && and || are left to right operators, therefore the first operator is always evaluated first.

Printf even though it shouldn't

I have this part of an if statement and I'm getting a weird output.
int x = 10;
if(1 < x < 5){
printf("F\n");
}
Why does it print "F"? Logically isn't the if statement false because x is greater than 1 but not less than 5?
In C, you can't chain comparisons like that. The expression 1 < x < 5 is evaluated as (1 < x) < 5: so for x = 10, the expression is (1 < 10) < 5. (1 < 10) is true, which C represents as the value 1, so the expression reduces to 1 < 5. This is always true, and your printf() if executed.
As level-999999 says, in C you need to explicitly combine single comparisons with && and ||.
If you are using C, you should have broken down the condition into two arguments :
if ( x > 1 && x < 5) {
printf("F\n");
}

if x=10 y=10 z=5 how is x<y<z=true? [duplicate]

This question already has answers here:
Why is a condition like (0 < a < 5) always true?
(4 answers)
Closed 9 years ago.
I have this question & in the answer it says that due to left to right associativity the result would be 1 that is true for this statement. This is the code.
#include<stdio.h>
int main ()
{
int i=0,x=10,y=10,z=5;
i=x<y<z;
printf("\n\n%d",i);
return 0;
}
But x is greater than z here so how is this happening ?
The expression x
(x < y) < z
so it becomes
(10 < 10) < 5
which further is evaluated into
0 < 5
which is true.
I think you wanted something like this:
x < y && y < z
Because of operator precedence and associativity
i = x < y < z;
is parsed as:
i = ((x < y) < z);
After substituting the variable values, this becomes:
i = ((10 < 10) < 5);
Since 10 < 10 is false, this becomes:
i = (0 < 5);
Since 0 < 5 is true, that becomes:
i = 1;
x<y<z is not a single valid expression. Instead it evaluates x<y first (operator precedence is done left to right here) as true/false (false in this case as they're equal), converts it to an int value of 0, and then compares this value with z.
Use (x < y && y < z) instead.
It first evaluates x < y which is false (0), then 0 < z which is true (1).
WHat C compiler does is, in x<y<z;
starts from left, so as x is not less than y therefore it replaces that expression with '0'
so it becomes 0<z and as that is true. it set the variable to 1.

Behaviour of && in C programming language

I am beginner in C programming language, recently I have read about Logical AND && operator.
I also know that, in C programming language all non-zero values are treated as TRUE.
NON-ZERO && NON-ZERO = 1
NON-ZERO && ZERO = 0
ZERO && NON-ZERO = 0
ZERO && ZERO = 0
But when I am dealing with the following program then I am not getting expected answer.
int main(){
int x, y, z;
x = y = z = -1;
y = ++x && ++y && ++z;
printf("x = %d, y = %d, z = %d, x, y, z);
return 0;
}
I am expecting
x = 0, y = 0, z = 0
but the answer is
x = 0, y = 0, z = -1
Can anyone please explain, Why I am getting this answer?
Edit:
In this question, I have not asked about the precedence of operators.
Because of Short-circuit evaluation, when x is 0, y and z don't really need to be evaluated since 0 && ANYTHING is 0.
Once x is incremented to 0, the result is 0, and that's what y gets.
z remains unchanged (-1).
x | y | z
----+----+-----
-1 | -1 | -1 //x = y = z = -1;
0 | -1 | -1 //++x && ... Now the whole expression is evaluated to 0
0 | 0 | -1 //y = ++x && ++y && ++z;
I only can think about that && evaluates in short circuit: given A && B, if A evaluates false then B is not evaluated.
So:
X becomes 0. && ++y && ++z does not evaluates since X/0/false && ...
y=0 as assigned from y = x/0/false
z remains unmodified since ++z does not get executed.
&& operator is evaluated pairwise, therefore I'm guessing C is evaluating
((++x && ++y) && ++z)
now, ++x will return zero therefore the first && will fail as will the second one without the need to evaluate ++y or ++z.
y = 0 since that is the result of the expression.
z is not touched
What happens is that ++y and ++z are never evaluated because the first part already ensures what the new value of y will be.
The first part of your statement is ++x && ... which is equivalent to 0 && ... and then we already know that y will be 0 in the end so the rest of the statement is not executed.
if you did this:
int main(){
int x,y,z,tmp;
x = y = z = -1;
tmp = ++x && ++y && ++z;
printf("x = %d, y = %d, z = %d, tmp = %d", x,y,z, tmp);
return 0;
}
You would get x = 0, y = -1, z = -1, tmp = 0
The left evaluation is guaranteed in the C99 standard. You can find it in the section 6.5.13 Logical AND operator
Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation;
there is a sequence point after the evaluation of the first operand. If the first operand
compares equal to 0, the second operand is not evaluated.
You can find more information about what is a sequence point on Wikipedia or in the Annex C of the C99 standard
For completeness (brain dump):
The term behind this sorcery is called short circuiting. Let's go over your code and then a brief blurb about why this happens. Looking at:
int main( void ) {
int x, y, z;
x = y = z = -1;
y = ++x && ++y && ++z;
printf( "x = %d, y = %d, z = %d, x, y, z );
return 0;
}
... we begin to break it down line by line. The first line:
int x, y, z;
... declares three integers, x, y and z. They are initialized to garbage values on the stack frame because there is no initialization (assignment operator). This line does not really matter, now let's look at the next one:
x = y = z = -1;
... we see that we are doing multiple assignments on the same line. Recall that the assignment operator will mutate the identifier to the left of the assignment operator (using the value to the right of the assignment operator) and return the value of x. This is known as assignment overloading. But again, this does not really matter -- the only important thing to realize is x, y and z are now all -1. Let's look at the next line:
y = ++x && ++y && ++z;
... Sorcery Yoda says. Let's add the parenthesis to make it more obvious which step is being evaluated first:
y = ( ( ++x ) && ++y && ++z );
... now looking at the inner-most parenthesis we see that it's a prefix increment of x, meaning we will increment the value of x and then return it. We note that x is originally -1 and it is now 0 after being incremented. This will resolve as follows:
y = ( 0 && ++y && ++z );
... now it's important to note that looking at our truth tables:
A | B | A && B
--------------
T | T | T
T | F | F
F | T | F
F | F | F
... for the AND logical operator we see that both F (AND) T, T (AND) F are F. The compiler realizes this and short circuits when ever it is evaluating a conjunction (AND) where a value is false -- a clever technique of optimization. It will then resolve to assigning y to be 0 (which is false). Recall that in C any non-zero value is true, only 0 is false. The line will look as follows:
y = 0;
... now looking at the next line:
printf( "x = %d, y = %d, z = %d, x, y, z );
... it should be obvious to you now that it will output x = 0, y = 0, z = -1.

Resources