Output: relational and ternary operator? - c

#include<stdio.h>
main()
{
int big,x=3,y=2,z=1,q=4;
big=( x>y ? (x<z ? 20:10 && y>x ? 50:10 ) : (y>z ? 40:10 || x<q ? 30:10));
printf("big =%d",big);
return 0;
}
&& is a relational operator so it should return a true or false value i.e 0 or 1, but in this case its not. Please explain whats the logic behind its output?
Output: big =10

It's all about operator precedence (and a distressing lack of parentheses).
The output I get when I run your program is nbig =10 (with no newline; you should add a \n to your format string).
The value assigned to big isn't the result of an && or || operator. Let's reduce that over-complicated expression, one step at a time. (I've confirmed at each step that the result is unchanged.)
big=(x>y?(x<z?20:10 && y>x?50:10) : (y>z?40:10 || x<q?30:10));
We know that x>y is true, so we can drop the test and the third operand of the corresponding ?: operator:
big=(x<z?20:10 && y>x?50:10);
Let's remove the extraneous outer parentheses, add some new around the third operand of the outer ?: operator, and change the spacing a bit:
big = x<z ? 20 : (10 && y>x?50:10);
We know that x<z is false, so we can drop that and the second operand of the outer ?::
big = (10 && y>x?50:10);
Obviously 10 is true, so:
big = (y > x ? 50 : 10);
And y > x is false, so the result is 10 -- which is what I get when I run your program.
You probably assumed that this:
a ? b : c && d ? e : f
is equivalent to:
(a ? b : c) && (d ? e : f)
but in fact it's equivalent to:
a ? b : ((c && d) ? e : f)
because the && operator binds more tightly than the ?: operator.
In any case, if this is real code, you should definitely add enough parentheses so that a reasonably knowledgeable reader can understand the code without having to consult an operator precedence table. Mixing &&, ||, and ?: can be particularly confusing. Breaking down the expression into subexpressions, and assigning each one to a temporary variable (so it has a meaningful name) can also be helpful.
The above applies if you're trying to write a complex expression. If you're trying to understand something that someone else has written, you pretty much have to parse it yourself. Try doing what I did: incrementally simplify the expression (by removing parts or adding parentheses) in ways that don't change the meaning, confirming at each step that you get the same result. And if it's production code (rather than a quiz, which this appears to be), consider complaining bitterly encouraging the author to write clearer code.

Let's make your expression a bit more explicit by adding parethesis to show the precedence:
((x>y) ?
((x<z) ?
20 : ((10 && (y>x)) ? 50 : 10)
) : (
(y>z)?40:((10 || (x<q))?30:10)
)
)
x is greater than y, so let's consider
((x<z) ?
20 : ((10 && (y>x)) ? 50 : 10)
)
and x is not less than z, so
((10 && (y>x)) ? 50 : 10)
y is not greater than x, so
10
You can see that the results are not actually of your logical operators. Because of the complexity involved, you should almost certainly express such an evaluation using if statements to break up the logic in a clean way.

Related

How is 0 used in conditional operator in C?

Conditional operator in C is used like this:
condition ? value_if_true : value_if_false
What does 0 mean when it's used in the value_if_false?
I've seen some people using it like this, for example.
a == b ? i++ : 0
It seems like it does nothing. Does this work like return 0 in other functions?
In C language, ternary is shorter version of if statement and it requires both statements, if_true and if_false. It would be like this (in fact it can have multiple statements for one case, separated with comma):
Short:
condition ? if_true : if_false;
Long:
if (condition) {
if_true;
} else {
if_false;
}
You can also assign the value if you put something infront of condition.
Short:
result = condition ? if_true : if_false;
Long:
if (condition) {
result = if_true;
} else {
result = if_false;
}
Now here is the trick. In C language, writing 0; is a valid statement, so your ternary becomes in longer version same as code below:
if (a == b) {
i++;
} else {
0; /* This is valid C statement */
}
Or if you have assignment too, it would be:
if (a == b) {
result = i++;
} else {
result = 0;
}
You can also do this:
int a;
/* Code here ... */
condition ? a = 5: 0;
That is effectively the same as:
if (condition) {
a = 5;
} else {
/* DO not touch a */
}
The ?: operator is a ternary operator, but it is not called "ternary" as some answers and/or comments here suggest. It just is the arity of the operator, just as + is a binary operator or as & is unary. If it has a name at all, it is called "Conditional Expression"-operator
It is not quite equivalent to if/else, because it is a conditional value (with the consequence, that both expressions must have the same type) in the first place, not a conditional execution. Of course, both types can be cast to make them equal.
In the case of what the OP does, a better option (if if shall not be used) is in my opinion:
a == b && i++;
which resembles a bit more logical what happens. But of course it is a matter of style.
The reason why someone might want to write a == b ? i++ : 0; is that s/he probably wants to have an (Caution! You are now entering an opinion-based area) easier and faster alternative to if (a == b) i++; - although this is of course opinion-based and I personally not share the same opinion.
One thing I can think of as a "blocker" at the if statement is the requirement to write the parentheses () which can be omitted by using the conditional operator instead.
"But why the 0?"
The C syntax requires a third operand for the conditional operator. Else if you would want to compile for example:
a == b ? i++;
you will get an error from the compiler:
"error: expected ':' before ';' token"
Or respectively, doing so:
a == b ? i++ : ;
would raise:
"error: expected expression before ';' token"
So they use 0 as kind of "syntax satisfier" to be able to use the conditional operator as replacement for the if statement. You could use any other numeral value here as well, but 0 is the most readable value, which signifies that it has no use otherwise.
To showcase the use at an example:
#include <stdio.h>
int main (void)
{
int a, b, c = 4;
a = 2;
b = 2;
a == b ? c++ : 0;
printf("%d",c);
return 0;
}
The output for c will be 5, because a == b.
Note that a == b ? i++ : 0 is different when used f.e. inside of an assignment like f.e.:
int c = a == b ? i++ : 0;
Here c is either getting assigned by i or 0, dependent upon a == b is true or not. If a == b is true, c is assigned by i. If a == b is wrong, c is assigned by 0.
Side Notes:
To view it from a technical point, ?= is called the "conditional operator". The conditional operator is one of the group of ternary operators.
If you want to learn more about the conditional operator ?=, look at ISO:IEC 9899:2018 (C18), ยง6.5.15 - "Conditional operator" for more information.
There's nothing special about 0 one could write
a == b ? i++ : 1
And it would behave the same way.
Only difference is when you assign the expression to say another variable:
int c = a == b ? i++ : 1;
// a == b -> c will be i++
// a != b -> c will be 1
However it's much cleaner to write
if (a == b) i++;
It helps to think of the ternary operator as a shorthand way or writing an if-else statement.
If(a == b){
i++;
}else{
//if assigned, return 0. Else do nothing.
}

Writing conditional statements without using if/else/?

I am looking to write conditional code without using (if/else/?/while etc...) in C language.
For example the following code:
if (Num>6) printf("T");
can be converted to (And still do the same task):
Num>6 && printf("T")
but the following:
bool larger;
if (Num>6) larger=true;
can't be replaced with:
bool larger;
Num>6 && larger=true;
Since lvalue is required as left operand of assignment
Any help? (I think && operation and the use of bool would be helpful)
Add parentheses around:
bool larger;
Num > 6 && (larger = true);
Why? Because = has lower precedence than && and >. That means the expression is parsed as
((Num > 6) && larger) = true;
which is an invalid assignment
Demo on compiler explorer

how will this statement execute conditional operation in c?

i have conditional operator's statement and i have no idea how its works.
there are two questions:
Question 1 : what will the following statement do :
quotient=(b==0)?0:(a/b) \\ here a,b,quotient is integer
Question 2 : Can preceding statement be written as follow ?
quotient=(b)?(a/b):0;
NOW MY QUESTION IS :
Question:1 :: we do not know b's value then how can we check this condition(b==0)
Question 2:: what (b) indicate ?
The conditional check in the C ternary conditional operator is an implicit comparison to not-zero.
In other words
quotient = b ? a / b: 0;
is the same as
quotient = b != 0 ? a / b : 0;
or the absurd
quotient = (b != 0) != 0 ? a / b : 0;
This is consistent throughout C, e.g. in an if, a for stopping condition, a while, &&, ||, &c.
If you try
int b = 0;
if (b) {
printf("Hello World");
}
Does not print anything while :
int b = 1;
if (b) {
printf("Hello World");
}
Prints Hello World. Why ? Because 0 is false and 1 is true.
If you do quotient=(b)?(a/b):0; it is interpreted to is b true ? or in other words is b evaluated to 1 (while, again, 1 is true and 0 is false)
C did not originally have a Boolean type. Conditionals are simply int values in C. 0 is false, and any other value is truthy. If the type of b is int, or it can implicitly convert to int, then (b) ? foo : bar does the same thing as (b == 0) ? bar : foo. (However, b==0 will evaluate to 1 or 0, whereas b by itself might have other nonzero values that if or ? consider truthy.)

C: "?:" operator expression equivalency

A few days ago i wrote a function that'd receive an int n greater than 0 and return the nth prime number. I wondered how much shorter that could be wrote and i came up with this:
int f(int i){int n=2,d=2,j=1;for(j;j<i;j+=n==d)n%d<1?n++,d=2:d++;return n;}
Then i saw the n%d<1 in the for and thought why not change it with just n%d and invert the order of the "?:" operator expressions, like this:
int g(int i){int n=2,d=2,j=1;for(j;j<i;j+=n==d)n%d?d++:n++,d=2;return n;}
But it just doesn't work, it gets stuck in an infinite loop. The d=2 never actually happens, i think. Can anyone point me out why not or what to read to figure it out?
If it's of any help, i'm running Ubuntu and compiling with gcc -std=c99 only.
It's an issue of operator precedence. ?: has higher precedence than ,, so
A , B ? C : D , E
parses as
A , (B ? C : D) , E
However, this doesn't apply to the middle part of ?: which works like it's surrounded by parens (because in a sense ? ... : is a bracketing construct):
A ? B , C : D
parses as
A ? (B , C) : D
because that's the only thing it can do without being a syntax error.
You can fix this by adding explicit parens:
n%d?d++:(n++,d=2);
The ternary ?: operator has higher precedence than the comma. Thus,
n%d?d++:n++,d=2
gets parsed as:
(n % d ? d++ : n++), d = 2
which is not what you want.
The reason it works in your first example is because there the comma is between the ? and the :, which act as paired delimiters just like parentheses, curly braces and square brackets do.

Unclear OR NOT syntax

Very basic question (I am a total noob in C...)
I have a piece of code written:
if(!_a[_item[i]] || _b[_item[i]])
Does this mean the next line should be run if:
item[i] is not present in a or in b
or does it mean it should be run if:
item[i] is not present in a or is present in b?
Thanks
It means item[i] is not present in a or is present in b
So, we can always look at the operator precedence tables, but I usually have some trouble following that. So let's write some code:
#include <stdbool.h>
#include <stdio.h>
int main() {
printf("%d\n", (!true || true)); // Outputs 1 (true)
}
So, let's see which of the two variants makes sense:
If we have ((!true) || true) then this makes sense.
If we have (!(true || true)) then this does not make sense.
So, we can pretty clearly say that these two expressions are the same:
(!_a[_item[i]] || _b[_item[i]])
((!_a[_item[i]]) || _b[_item[i]])
And thus, we know that the next line will run if _item[i] is not present in a or it is present in b.
Although an answer has been selected for this question, I'm going to chime in anyway.
The code
if(!_a[_item[i]] || _b[_item[i]])
Does not determine the (non) presence of _item[i] in _a or _b. What it does is say:
The numerical value of the element _item[i] of array _a is zero or the numerical value of
the element _item[i] of array _b is non-zero
Whether that maps to the concept of presence is an architectural decision that is irrelevant to how the if statement is processed.
! has higher precedence than ||. The first term is negated, the second one isn't. It's equivalent to ( (!(_a[_item[i]])) || _b[_item[i]] )
Check the operator precedence (e.g. on Wikipedia), you'll find that ! is evaluated before the || and thus the expression is parsed like this:
if((!_a[_item[i]]) || _b[_item[i]])
btw. if you see (!A || B) this is known as implies in logic: A implies B == !A || B

Resources