Hey thank you very much for your time! I'm having trouble understanding the syntax of a statement in my audio coding textbook. In one example there is a print function that goes like this
printf("%d semitones up or %d semitones down\n", interval,
interval ? 12-interval : 0 );
The part I don't understand is the conditional operator, or "?". It seems like I should just read it as "if interval does not equal 0, interval = 12 - interval" but the syntax here seems strange. I'm used to the conditional operator being a more fleshed out statement, like:
a = b > c ? b : c;
"If b is bigger than c, than a = b; else a = c"
Could someone point me to any other reference for this, or explain more about this syntax? I can't find similar examples.
You're almost right, but there's no assignment taking place. It's saying "if interval is non-zero, pass 12 - interval to the printf statement, otherwise pass 0".
In general the ternary operator looks like this:
a ? b : c
Where a, b, and c are all expressions. If a evaluates to non-zero, the ternary operator evaluates as if it were b, and if a evaluates to zero, the ternary operator's result is the result of evaluating c.
Your second example is a combination of the ternary operator and the assignment operator. The ternary operator itself doesn't perform any assignments.
Any expression that results in a boolean will do. In the case of C, where integers can be used as booleans, the value 0 is considered false and anything else is considered true.
So, in your case, interval ? 12-interval : 0, means: if interval is nonzero, use 12-interval, otherwise, use 0. To be extra verbose, you could rewrite it to:
interval != 0 ? 12-interval : 0
Related
I wanted to know if there's a way to omit second or third part of the ternary operator?
I already read this and similar ones but they didn't help.
What I specifically want is something like:
x == y ? x*=2;
however this gives me error as gcc expects another expression also. So are:
x == y ? x *=2 : continue;
x == y ?: x /=2;
What can I do in these situations except:
if(x == y) do_something;
Edit for further clarification:
As my question seems to be confusing and got all kinds of comments/answers my point was when thinking logically, an else is required after if , so is the default statement in a switch however, neither are mandatory. I was asking if it's the case with ?: also and if so, how.
I wanted to know if there's a way to omit second or third part of the ternary operator?
No, not in standard C.
You can substitute expressions or statements that do not use the conditional operator at all, but in standard C, the conditional operator requires three operands, just like the division operator (/) requires two. You cannot omit any.
Nor is it clear why you want to do. The primary thing that distinguishes the conditional operator from an if [/ else] statement is that expressions using the conditional operator are evaluated to produce values. If you're not interested in that value then using a conditional expression instead of a conditional statement is poor style. A standard if statement is much clearer, and clarity is king. This is a consideration even when you do want the value.
What can I do in these situations except:
if(x == y) do_something;
You can go have a coffee and hope the mood passes.
But if it doesn't, then the logical operators && and || have short-circuiting behavior that might suit, as #EricPostpischil already observed:
a && b is an expression analogous to if (a) b;. It evaluates a, after which there is a sequence point. If a was truthy then it evaluates b and that is the result of the expression; otherwise it does not evaluate b and the value of a is the value of the expression. That is the C version of the hypothetical a ? b : (nothing), and why C does not need the latter.
Similarly, a || b is an expression analogous to if (!a) b;. b is evaluated and yields the result of the expression if and only if a is falsey. That is the C version of the hypothetical a ? (nothing) : b.
But here again, it is poor C style to use && and || expressions exclusively for their side effects. If you don't care about the result of the operation, then use an if statement.
Or perhaps poor style is the point? If you're shooting for an entry in the International Obfuscated C Code Contest then abusing operators is par for the course. In that case, you could consider rewriting your expressions to use the ternary operator after all. For example,
x == y ? x *=2 : continue;
could be written as x *= ((x == y) ? 2 : 1), provided that you weren't actually trying to get loop-cycling behavior out of that continue. And
x == y ?: x /=2;
could be rewritten similarly. Though if you were actually looking toward IOCCC, then there are better obfuscation options available.
For the purpose asked about in this question, in which the result value of the conditional operator would not be used:
For a ? b : c without b you can use a && b, which will evaluate b if and only if a is true.
For a ? b : c without c you can use a || c, which will evaluate c if and only if a is false.
These expressions will have different values than a ? b : c, but that does not matter when the value is not used.
Without some exceptional circumstance to justify this, most experienced programmers would consider it bad practice.
GCC has an extension that uses the first operand for a missing second operand without evaluating it a second time. E.g. f(x) ? : y is equivalent to f(x) ? f(x) : y except that f is only called once.
Similar to the 'hyphen-ish' character of "-1" being called "unary minus", "?:" is called "trenary" because it requires 3 parts: the condition, the "true" case statement and the "false" case statement. To use "?:" you must supply 3 "terms".
Answering the question in the title, no, you cannot omit one part.
The following responds to "What can I do in these situations except:"
Given that your two examples show an interest in performing (or not) a mathematical operation on the variable 'x', here is a "branchless" approach toward that (limited) objective. ("Branchless" coding techniques seek to reduce the impact of "branch prediction misses", an efficiency consideration to reduce processing time.)
Note: the for() loop is only a "test harness" that presents 3 different values for 'y' to be compared to the value of 'x'. The variable 'n' makes more obvious your OP constant '2'. Further, as you are aware, performing multiplication OR division are two completely different operations. This example shows multiplication only. (Replace the '*' with '/' for division with the standard caveat regarding "division by zero" being undefined.) Depending on the probability of "cache misses" and "branch prediction" in modern CPUs, this seemingly complex calculation may require much less processing time than a 'true/false branch' that may bypass processing.
int n = 2; // multiplier
for( int y = 4; y <= 6; y++ ) { // three values for 'y'
int xr = 5; // one value for 'xr'egular
int xb = 5; // same value for 'xb'ranch
(xr == y) ? xr *= n : 1; // to be legitimate C
// when x == y the rhs becomes (n-1)*(1)+1 which equals n
// when x != y the rhs becomes (n-1)*(0)+1 which equals 1 (identity)
// Notice the rhs includes a conditional
// and that the entire statement WILL be evaluated, never bypassed.
xb *= ((n-1)*(xb==y))+1;
printf( "trenaryX = %2d, branchlessX = %2d\n", xr, xb );
}
Output
trenaryX = 5, branchlessX = 5
trenaryX = 10, branchlessX = 10
trenaryX = 5, branchlessX = 5
I hope this makes clear that "trenary" means "3 part" and that this digression into "branchless coding" may have broadened your horizons.
You can use the fact that the result of comparison operators is an int with value 0 or 1...
x == y ? x*=2;
x *= (x == y) + 1; // multiply by either 1 or 2
But a plain if is way more readable
if (x == y) x *= 2;
x == y ? x*=2 : 1;
The syntax requires all three parts... But, if you write code like this, you will lose popularity at the office...
Repeating for those who might have missed it: The syntax requires all three parts.
Actually, you shouldn't do this because as #user229044 commented, "if (x==y) do_something; is exactly what you should do here, not abuse the ternary operator to produce surprising, difficult-to-read code that can only cause problems down the line. You say "I need to know if that's possible", but why? This is exactly what if is for."
As in ternary operator without else in C, you can just have the third/second part of the ternary operator set x to itself, for example, you can just do:
x = (x == y ? x *= 2 : x);
or
x == (y ? x : x /= 2);
I'm starting to learn to program in c, and I thought I was already pretty confident with the precedence of operators, until I did this:
a > b ? c = a : (c = b);
Of course at the first time I didn't use parenthesis on the last sentence, but since that ended up causing compiling issues I searched how to solve that problem on this forum and I read that adding parenthesis could do the job. However, I thought that the expressions inside parenthesis get executed before anything else written in the same line, which would mean that the c = b sentence was executed first and then the ternary operator. I did something similar but easier to read in order to get a better idea of what was happening with this operator precedence thing and tried executing this line:
printf("Number is %d", i) + (i = 5);
I know this expression returns returns a value, but since I don't need it and this isn't a line that I will keep for more than 5 seconds, I won't store it in any variable. What gets my attention in this case is that, when I execute the code, I doesn't show up on the screen with the value 5, but instead it uses the previous value, which means that the computer is just reading it from left to right. When I do:
(i = 5) + printf(Numer is %d, i);
it first does the assignment of i and only after that the printf function is executed. My question is: how does the computer execute an expression that uses operators of different orders of precedence? It clearly doesn't run first the operator with the highest precedence, because in the first printf the value stored wasn't the one assigned on the parenthesis, but it also doesn't just read from left to right because in that case there would be no operator precedence. How does it work?
Parenthesis and operator precedence only dictate how operands are grouped. It does not dictate the order of evaluation.
In this expression:
a > b ? c = a : (c = b);
The three parts of the ternary operator are a > b, c = a, and c = b respectively. This operator also has the property that only one of the second and third clause are evaluated, based on the result of the first. Formally speaking, there is a sequence point between the evaluation of the first clause and of either the second or third. So a > b is first evaluated. If it is nonzero, c = a is evaluated, otherwise c = b is evaluated.
In this expression:
printf("Number is %d", i) + (i = 5);
There is nothing that dictates whether printf("Number is %d", i) or i = 5 is evaluated first. Unlike the ternary operator, there is no sequence point between the evaluation of the operands of the + operator. This expression also has a problem: i is both read and written in the same expression without a sequence point. Doing so triggers undefined behavior. This is also true for:
(i = 5) + printf(Numer is %d, i);
On a side note, this:
a > b ? c = a : (c = b);
Can be more clearly written as:
c = a > b ? a : b;
The code below compiles well
int a=5,b=4,c;
a>b?30:40;
Also does,
int a=5,b=4,c;
a>b?c=30:40;
But why this does not work?
int a=5,b=4,c;
a>b?c=30:c=40;
You are being bitten by precedence. ?: has very low precedence, but not as low as = or , (see the operator precedence table).
Your code is parsed as:
(a>b ? c=30 : c) = 40;
Rather than:
a>b ? c=30 : (c=40);
You don't need parenthesis around c=30 because ? and : act like parentheses to the expression within.
Believe it or not, (a>b ? c=30 : c) = 40 is valid C++ (but not valid C). The expression (a>b ? c=30 : c) is an lvalue referencing the variable c, to which 40 is assigned.
You've run into a precedence problem with the = operator. If you insist on assignment inside of your ternary operator, merely wrap the sub expressions in parentheticals:
int d = a > b ? (c = 30) : (c = 40); // explicit precedence
The last one:
int a=5,b=4,c;
a>b?c=30:c=40;
fails because it's trying to assign 40 to a>b?c=30:c, which obviously won't work. The = has lower precedence, and a>b?c=30:c is a valid expression (though you can't assign to it). The = in the c=30 part is sort of an exception because it's in the middle of the ternary operator, between the ? and the :. To fix it you'd simply need to add parentheses around the c=40 so that it's evaluated as a single value for the 'else' part of the ternary operator, i.e. a>b?c=30:(c=40);
The second example
a>b?c=30:40;
doesn't assign anything to c unless a is greater than b... which it is when a is 5 and b is 4, as in this case; but note that if a were not greater than b, no assignment would occur.
From the first example
a>b?30:40
is a valid expression, with a value of 30 or 40, but you're not doing anything with that value so of course it serves no purpose there.
Of course, you'd normally use something more like:
c = a>b ? 30 : 40;
where a>b ? 30 : 40 will evaluate to 30 or 40, which is then assigned to c. But I suspect you know that and simply want to know why the c=40 is not treated as a single value for the 'else' part of the ternary operator in the last example.
Following program gives error
#include<stdio.h>
int main ()
{
int a=10,b;
a>=5?b=100:b=200;
printf("\n%d",b);
}
the error is
ka1.c: In function ‘main’:
ka1.c:5: error: lvalue required as left operand of assignment
now if I replace the line
a>=5?b=100:b=200;
by
a>=5?b=100:(b=200);
and then compile then there is no error.
So I wanted to know what is wrong with
a>=5?b=100:b=200;
The ternary operator (?:) has higher precedence than the assignment operator (=). So your original statement is interpreted as:
((a >= 5) ? (b = 100) : b) = 200;
Write it like this instead:
b = (a >= 5) ? 100 : 200;
This is idiomatic C. (The brackets around the condition are not really necessary, but they aid readability.)
You're using the ternary operator incorrectly. Both of your examples are wrong, even though one compiles. The expression evaluates to either the second or third sub-expression depending upon the truth value of the first.
So a ? b : c will be the same thing as b if a is true, or c if a is false.
The proper way of using this operator is to assign the result to a variable:
b = a>= 5 ? 100 : 200;
Because it tries to do: (a>=5?b=100:b)=200
But the thing in parentheses is not lvalue.
Here is a c program.I am getting a strange output.
When num1=10 and num2=20->
#include<stdio.h>
void main()
{
int num1=10,num2=20;
clrscr();
if(num1,num2)
{
printf("TRUE");
}
else
{
printf("FALSE");
}
getch();
}
Output:
TRUE
when num1=0 and num2=220
Output:
TRUE
But when num1=0 and num2=0:
Output:
FALSE
Why does this happen?
also,what does this given below code mean:
if(num1,num2)
Thanks in advance!
You're using the comma operator. That operator first evaluates its first operand, then drops the result on the floor and proceeds to evaluate and return its second operand.
That's why your program only prints FALSE if num2 evaluates to false in a boolean context (like e.g. 0, 0.0 or NULL).
In:
if(num1,num2)
the last expression overrides all preceeding ones so it's the same as:
if(num2)
since, num2 is 0, you get FALSE.
If you check this out,
http://msdn.microsoft.com/en-us/library/2bxt6kc4(v=vs.71).aspx
the , stands for sequential evaluation, meaning the expressions are evaluated one after another, the last being your num2.
Learn about comma operator in c http://en.wikipedia.org/wiki/Comma_operator.
i=(a,b) means store b in i.
Everything else than 0 in c is true.
so if(3) if (-3) all are true
only if(0) is false
if(num1,num2)
Is a use of the comma operator. The Comma operator calculates the first operand and discards the result then the second operand and returns the result. Thus (a, b) calculates a, calculates b and then returns b.
This should clear up your confusion for the logical cases, in each of them the statement has the effect of looking at the value of b.
if(num1,num2)
is not a syntax error, but it is a logic error. Basically, this will resolve to being only
if(num2)
Only the last variable is evaluated.
I assume what you want is 'if a and b are true'. The comma like you are using means to evaluate just the last variable.
What I think you want is:
if(num1 && num2) /* num1 AND num2 */
You need to use && (logical AND) not a single & (Which is bitwise AND)