This question already has answers here:
Yet Another Conditional Operator Nesting Question
(2 answers)
Why is the conditional operator right associative?
(3 answers)
To ternary or not to ternary? [closed]
(54 answers)
Closed 5 years ago.
I just got a question idea after having misunderstood a friend's statement.
My friend told me: I just taught a colleague how to do a if/else in one line in c.
Example:
int i = 0;
i < 0 ? printf("i is below 0") : printf("i is over or equal to 0");
For now, nothing new, it's called a ternary and most people know about that kind of statement BUT I first understood that:
I just taught a colleague how to do a IF / ELSE IF / ELSE in one line.
Since I don't / didn't know that doing such a thing is possible I tried to do something like
int i = 0;
i < 0 ? printf("i is below 0") : i == 0 ? printf("i equal 0") : printf("i is over 0");
Is it actually possible to do a if / else if / else "ternary". Or is there a way to do such a thing without having an horrible piece of code?
If you see e.g. this conditional expression reference you can see that the format of a "ternary expression" is
condition ? expression-true : expression-false
All three parts of the conditional expressions are, in turn, expressions. That means you can have almost any kind of expression, including nested conditional (ternary) expressions in them.
It should be noted that conditional expressions might make the code harder to read and understand, especially if used badly or if one attempt to put too much logic and nesting into the expressions.
This is definitely valid.
Or you could try something like this -
printf(i < 0 ? "i is below 0" : i == 0 ? "i equal 0" : "i is over 0");
C has both statements and expressions. There are two different kinds of syntactical things. BTW lines don't matter much in C (except for the preprocessor).
Expressions (like f(1,x+y) or even x=y++) are a special kind of statements (the most common one).
As an extension to C, the GCC compiler adds statement expressions, beyond what the C11 standard (read n1570) defines. Please download then read that n1570 repoort.
if is for conditional statements but the ternary ?: operator is for expressions (with all three operands being sub-expressions).
Some programming languages (notably Lisp, Haskell, Scheme, Ocaml) have only expressions and don't have any statements.
Related
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 4 years ago.
can someone explain to me why this code prints the decremented amount? Since (4 <= 3) is false, shouldn't it proceed to print "Hi"?
int main()
{
int amount = 4;
if((amount%5) <= (--amount))
printf("%d", amount);
else
printf("Hi");
}
Turns out this code is undefined. You've got the expression
(amount%5) <= (--amount)
But the key question is, does the amount%5 part use the old value of amount, or the new, after being decremented by the --amount part? And the answer is: We have no idea. There's no way to tell. There's no rule in the C language to tell us.
You might think the code has to be evaluated left-to-right, that the amount%5 part has to happen first, before the --amount part has a chance to happen. But that's not the way it works. Since it's undefined, anything could happen.
If it's evaluated more or less left-to-right, then we have
if(amount%5 <= --amount)
which evaluates to
if(4%5 <= --amount)
which evaluates to
if(4 <= --amount)
which evaluates to
if(4 <= 3)
which is false, so you might expect it to print "Hi". But, if it's evaluated more or less right-to-left, it's
if(amount%5 <= 3)
which evaluates to
if(3%5 <= 3)
which evaluates to
if(3 <= 3)
which is true.
(You'll notice that I have removed some extra parentheses, since they don't do anything.)
I hasten to add that these are not the only two possibilities. The rules say that once an expression is undefined, literally anything can happen -- the behavior doesn't have to be anything we might consider "reasonable" at all.
So why is it undefined? In this case it's because you have a variable -- amount -- which appears twice in the expression, and where one of those appearances is a modification (the --amount part), and where the other one uses the variable's value. The C Standard explicitly tells us that in this case (a) we can't tell whether the use of amount uses the old or the modified value, and furthermore that (b) this flaw in the expression -- this simultaneous modification and use -- renders the whole expression (and actually the whole program it's in) undefined.
So how do you fix it? The answer is simple, and it's the punchline of an old joke: Don't do that. Don't write expressions where a single variable (or other object) is both modified and used. It's fine to write --amount, just don't do it in an expression that's also using the value of the variable amount somewhere else.
Questions like this come up often. The canonical SO answers, which others are already redirecting you to, are collected under the question Why are these constructs (using ++) undefined behavior in C?. There's more I could say about the rules concerning undefined expressions, but you can find those details over at that question.
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" );
Is there any method to use a conditional statement inside other statements, for example printf?
One way is using ternary operator ? : eg:
printf("%d", a < b ? a : b);
Is there a method for more complicated conditions?
There is no need for more complex expressions, the conditional operator is already bad enough. There is no language feature for it. Instead, write a function.
printf("%d", compare(a,b)); // good programming, readable code
printf("%d", a<b?(x<y?x:y):(x<y?y:x)); // bad programming, unreadable mess
Every conditional statement return 1 or 0. These values are int
So if you do printf("%d",a>b); then either 1(true) or 0(false) will be printed.
In your example you are using ternary operator a<b?a:b.
If condition is true then a will be printed else b.
You cannot put statements into printf at all, you only can put expressions there. The ternary operator forms an expression. An expression is basically a tree of operators and operands, however there are a few funny operators allowed, like the ',' comma operator or the '=' assignment operator. This allows expressions to have side effects.
Greetings to all the expert again , and again I stumble across a few questions.
The Story :
I read a book mentions that a sequence point which is ; is a point where all the side effect before it should be evaluated before it advanced to the next statement.In order to make the context of my question clean , I will write a simple code.
The Code :
while (guess++ < 10)
{
printf("%d \n" , guests);
My Thinking and the Question:
1.)From the above code, the while statement test condition guess++ < 10 is a full expression.So in my mindset it is not a statement because it doesn't end with a ;.
2.)Since a postfix increment operator is used , therefore the guess value evaluated before it is incremented.
3.)The book mention that the increment operation is carry out right after the guess variable is used for the relational operation , then only the printf() function would carry out its duty.
4.)My question is that , since the test condition doesn't end with a ; , therefore it's not a statement . But why the increment operation implemented before printf() function is called , but not after the print() function only it is being incremented??
5.)Maybe this is a side question , the book mention that while is a structured statement , but why didn't I see a trailing ; is append on it while(testcondition);.
6.)It might sounds like a silly question , but sometime when I read some source code written by others , I will saw some of them place the open braces { of while loop on the same line with the while() , which causes it to be like that while(testcondition){ . Is this a convention or is there any special reason for doing this??
Thanks for spending time reading my problems , your help is much appreciated.
Answering question 1: The code between the brackets of a while loop is actually a full expression. From wikipedia:
This category includes expression statements (such as the assignment a=b;), return statements, the controlling expressions of if, switch, while, or do-while statements, and all three expressions in a for statement.
A good description of a full expression can be found in the C faq:
full expression
The complete expression that forms an expression statement, or one of the controlling expressions of an if, switch, while, for, or do/while statement, or the expression in an initializer or a return statement. A full expression is not part of a larger expression. (See ANSI Sec. 3.6 or ISO Sec. 6.6.)
It's important to note that a full expression has nothing to do with a statement or the semi-colon token.
So lets dig into this a little bit. Fixing up your code snippit I came up with this:
#include <stdio.h>
int main(void)
{
unsigned guess = 0;
while (guess++ < 10)
{
printf("%d " , guess);
}
return 0;
}
Which produces this output:
1 2 3 4 5 6 7 8 9 10
So that means that the evaluation would be equivalent to this code:
while (guess < 10)
{
guess++;
printf("%d " , guess);
}
The answer to question 5 can be found in this stackoverflow question:
In C/C++ why does the do while(expression); need a semi colon?
I just wrote the following line of code:
if (++(data_ptr->count) > threshold) { /*...*/ } // example 1
My intent is to increment the count variable within the data structure that data_ptr points to before making the comparison to threshold, and this line of code works.
If I had instead wanted to increment data_ptr before making the comparison, I would have written this:
if ((++data_ptr)->count > threshold) { /*...*/ } // example 2
Out of curiosity, I also tried this line of code:
if (++data_ptr->count > threshold) { /*...*/ } // example 3
And found that it behaves exactly the same as the first one.
First question: Why does example #3 work the same as example #1? Is it a matter of operator precendence? Something in the standard? I had to write a quick test program becuase the answer was not obvious to me.
Second question: Should I write this if statement differently? I could perform the increment first, on its own line, and then test the condition in order to avoid any possible confusion. Is this necessary, or are the first two examples obvious enough on their own?
1) Precedence
2) Preference
Yes, this is a question of operator precedence. The arrow operator has higher precedence than the increment operator.
To answer your second question, I would generally separate this type of construct out into two separate statements:
++(data_ptr->count);
if(data_ptr->count > threshold) { /*...*/ }
This emphasizes what is going on and eliminates possible confusion. However, this is probably a question of preference.
Operator precedence dictates the behaviour you observed.
It wouldn't hurt much if you separated the increment from the comparison in this example, but sometimes you want to have a condition with increment in the middle of a sequence of conditions, and then trying to separate the increment from the test can hurt the readability of the code by introducing nesting that would otherwise be unnecessary.
For example:
if (...1...)
...2...
else if (++data_ptr->count > threshold)
...3...
else
...4...
Versus:
if (...1...)
...2...
else
{
++data_ptr->count;
if (data_ptr->count > threshold)
...3...
else
...4...
}
The -> operator binds tighter than ++.
They're both well-defined and I think they're easy to read. Things would only get dodgy if you had additional references to data_ptr in the same expression.