C: "?:" operator expression equivalency - c

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.

Related

C error:lvalue required as left operand of assignment

#include<stdio.h>
int hailstone(int n){
int length=1;
while(1<n){(n%2)?n=3*n+1:n/=2;length++;}//error
//while(1<n){(n%2)?n=3*n+1:(n/=2);length++;} right
return length;
}
int main()
{
int n;
scanf("%d",&n);
printf("%d\n",hailstone(n));
}
There is an error in line four,the gcc compiler said lvalue required as left operand of assignment,but if i add brackets it will be right.like line five,and i don not know why.
Despite shoving all the logic into one line, the problem is actually in one expression (pardon me for adding spaces):
(n%2) ? n=3*n+1 : n/=2
The precedence rules for C expressions are like that. Assignment (and that includes compound assignment) binds less tightly than ?:. So the compiler has to interpret what you wrote as:
((n%2) ? n=3*n+1 : n) /=2
Since ?: doesn't produce an lvalue (something that can appear on the left of an assignment), you get an error. Your use of parentheses forces the precedence to match what you wanted.
But an even better way to write that is to not be "clever" and think there is some "elegance" in using as much tokens as possible in a single expression. Here's another version, which is far more readable, and easier to verify as correct:
if (n%2) {
n = 3*n+1;
} else {
n /= 2;
}
And it's no less efficient than using a conditional expression.
Here the compiler takes l value as
((n%2) ? n=3*n+1 : n) /
and r value as
2
Since ((n%2) ? n=3*n+1 : n) / = 2 is an invalid statement and l value is not a variable, compiler throws error. You can provide the precedence of execution to the compiler by adding brackets.

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

Output: relational and ternary operator?

#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.

If statement with ? and : [duplicate]

This question already has answers here:
What does the question mark and the colon (?: ternary operator) mean in objective-c?
(13 answers)
Closed 9 years ago.
I heard about a kind of If statement which use ? and : in C
I dont know how to use it and I cant find anything about it.
I need to use it in order to shorten my code
any help would be appreciated.
?: is ternary operator in C (also called conditional operator). You can shorten your code like
if(condition)
expr1;
else
expr2;
to
condition ? expr1 : expr2;
See how it works:
C11: 6.5.15 Conditional operator:
The first operand is evaluated; there is a sequence point between its evaluation and the
evaluation of the second or third operand (whichever is evaluated). The second operand
is evaluated only if the first compares unequal to 0; the third operand is evaluated only if the first compares equal to 0; the result is the value of the second or third operand
(whichever is evaluated),
As others have mentioned, it's called the ternary operator. However, if you didn't know that, it would be somewhat difficult to Google it directly since Google doesn't handle punctuation well. Fortunately, StackOverflow's own search handles punctuation in quotes for exactly this kind of scenario.
This search would yield the answer you were looking for. Alternately, you could search for "question mark and colon in c" on Google, spelling out the name of the punctuation.
First you have the condition before the ?
Then you have the expression for TRUE between ? and :
Then you have the expression for FALSE after :
Something like this:
(1 != 0) ? doThisIfTrue : doThisIfFalse
The ternary operator ?: is a minimize if statement which can reduce this:
if(foo)
exprIfTrue();
else
exprIfFalse();
To this:
(foo) ? exprIfTrue() : exprIfFalse() ;
Personally, I avoid using it because it easily becomes unreadable. The only good example of use is to display the status of a flag in a printf:
int my_flag = 1;
printf("My flag: %s\n", my_flag ? "TRUE" : "FALSE" );

expected expression before return

the following c statement is not passing through compiler .error being "expected expression before return".
int max( int a,int b)
{
a>b?return a:return b;
}
and yeah ,i know i can write this for finding max as
return a>b?a: b;
which is quite okay and will run perfectly.
but my question is what is exact problem with the first code.why cant we use return in ternary opoerator,although we can use function call quite easily over there?
THANKS in advance!!!
The C grammar says that the things after the '?' and the ':' must be expressions - return is not an expression, it is a statement.
The operands of ternary ?: are expressions. A return statement is a statement, not an expression.
?: is an operator not a control flow construct, so the whole thing with operands must be an expression, and return statements (or any statement) are not valid sub-expressions.
?: is not simply a shorthand for if-else (which is a control flow construct); it is semantically different.
if( a > b ) return a; else return b;
on the other hand is what you were trying to do, and entirely valid (if perhaps ill-advised stylistically).
The second and third parts of the ternary expression are expected to yield values, not be return statements as in your example.
Ternary operator needs expression,return is a statement.
More about conditional operator here.

Resources