Consider the code:
if(x = a/b, a%b)
printf("do this");
else
printf("do that");
Now if I replace if statement by if(x = a/b && a % b). Then it works also. So I want to know that replacing comma by && operator and vice-versa works always or not in if-else and loops
They are quite different!
In the first example, , is the comma operator, which is a binary operator that evaluates its first operand and discards the result, and then evaluates the second operand and returns this value (and type).
So,
if(x = a/b, a%b)
is equivalent to (thanks to #jaket)
x = a/b;
if(a%b)
a%b will always be evaluated.
For the second one:
if(x = a/b && a % b)
is equivalent to
x = (a/b) && (a%b);
if( x )
a%b will only be evaluated if a/b (i.e. a/b is not zero) is true.
if you replace the comma operator by &&, you're changing the logic slightly. What the comma operator does is it will execute x = a/b and "discard the result", i.e. it's not taken into consideration for the if's condition, only a%b is taken into account.
if you do
if(x = a/b && a % b)
then "do this" will be printed if and only if a/b is non zero and a % b is non zero. Whereas with the comma operator, "do this" is printed only if a % b is non zero.
if(x = a/b, a%b)
is an obfuscated, unreadable way of writing
x = a/b;
if(a%b)
But
x = a/b && a % b
is equivalent to
x = ( (a/b) && (a%b) );
To sum it up, don't mix a whole lot of different operators on the same line. The only thing you achieved with it was to confuse yourself, while creating bugs.
The && operator forces the the result of a/b as well into consideration in determining the expression x = a/b && a%b, In case of ,, the result of a/b is ignored. So replacing , with && will not work always. And not the right thing to do,
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);
#include <stdio.h>
int main() {
int a = 1;
int b = a || (a | a) && a++;
printf("%d %d\n", a, b);
return 0;
}
when I ran this code the results were 1 and 1.
According to the C language Operator Precedence the operation && is supposed to happen before the operation ||. So shouldn't the result be 2 1 ? (a = 2, b = 1)
when OR'ing expressions in C, a shortcut is taken, I.E. as soon as an expression is evaluated to TRUE, the rest of the OR'd expressions are not evaluated
The first expression a evaluates to TRUE, so all the rest of the expressions are not evaluated, so a is never incremented
When applying the operator precedence rules, the expression is equivalent to:
int b = a || ((a | a) && a++);
The evaluation or the operands to || and && is performed from left to right and shortcut evaluation prevents evaluating the right operand if the left operand can determine the result: since a is non zero, a || anything evaluates to 1 without evaluating the right operand, hence bypassing the a++ side effect.
Therefore both a and b have value 1 and the program prints 1 1.
Conversely, if you had written int b = (a || ((a | a)) && a++;, the left operand of && would have value 1, so the right operand need to be evaluated. a++ evaluates to 1 but increments a, so b have final value 1 and a is set to 2, producing your expected result.
The confusion comes from equating operator precedence with order of evaluation. These are two separate notions: operator precedence determines the order in which to apply the operators, but does not determine the order of evaluation of their operands.
Only four operators have a specified order of evaluation of their operands: &&, ||, ? : and , and the first 2 may skip evaluation of one, depending on the value of the other operand and the third only evaluates the first and only one among the second and third operands. For other operators, the order of evaluation of the operands is unspecified, and it may differ from one compiler to another, one expression to another or even one run to another, although unlikely.
When I try to put a || (a | a) into a parenthesis. The result was as you expected.
So I guess that when C compiler executes an OR operator and it get a True value to the OR, the execution will finish immediately.
In your case, when the compiler executed the a || (a | a) (1 || something) operation. Value of b will be declared to 1 right away and a++ operator won't be execute.
Increment operator not working.
I was learning C language expressions. I've also tried different combinations of increment operators (prefix and postfix) on the variables but the output is coming out to be same.
int i=-3, j=2 ,k=0,m;
m=++i&&++j||++k;
printf("%d%d%d%d\n",i,j,k,m);
I expect the output to be -2311 but it comes out to be -2301.
i and j are incremented because i needs to be evaluated. j also needs to be evaluated because i is non-zero.
But since this combined expression is non-zero, || short-circuits, and k++ is not evaluated or executed.
On the other hand, bitwise operators don't short-circuit. They also don't convert to booleans. If you want to evaluate all conditions and keep the same result you could write
m= (!!++i) & (!!++j) | (!!++k);
using the double negation trick to convert integer value to boolean.
Or spare another statement and simplify to (courtesy from user694733):
++i; ++j; ++k;
m = i && j || k;
The && and || operators short-circuit - depending on the value of the left-hand side of the expression, the right hand side may not be evaluated at all.
For the expression a || b, if a is non-zero, then the result of a || b is 1 regardless of the value of b, so b is not evaluated. For the expression a && b, if a is zero, then the result of a && b is zero regardless of the value of b, so b is not evaluated.
In your case, the result of ++i && ++j is non-zero, so ++k is not evaluated.
What is the difference between & and && in C?
My teacher gave me this example:
int a = 8;
int b = 4;
printf("a & b = %d\n", a & b);
printf("a && b = %d\n", a && b);
Output:
a & b = 0;
a && b = 1;
I'm not sure why this would return true in one scenario and false in another.
& is bitwise and and && is logical and.
The expression x && y will return 1 if both x and y is non-zero, and 0 otherwise. Note that if x is zero, then y will not be evaluated at all. This will matter if y is an expression with side effects. This behviour is called short circuiting.
The expression x & y will perform a bitwise operation on each individual bit in x and y. So if x is 1010 in binary and y is 1100 then x & y will evaluate to 1000. Note that the return value of x & y should NOT be interpreted as a Boolean value, even if it's possible. In early C, the operator && did not exist, and because of that & was used for this purpose.
One way to explain it is that you could imagine that & is the same thing as applying && on each individual bit in the operands.
Also note that & has lower precedence than &&, even though intuition says that it should be the other way around. This also goes for comparison operators, like <, <=, ==, !=, >=, >. This goes back to the time when C did not have the operators && and || and the bitwise versions was used instead. At this time, it made sense, but when the logical operators were added, it did not anymore. Kernighan and Ritchie admitted that it would have made more sense, but they did not fix it because this would break existing code.
I'm not sure why this would return true in one scenario and false in another.
The return value from x & y should not be treated as a Boolean value at all. However, it can (depending on how the code is written) be treated as a Boolean array. If you have two integers, flags1 and flags2 then the result of flags1 & flags2 will denote which flags that are toggled in both flags1 and flags2.
The & operator performs a bit-wise and operation on its integer operands, producing an integer result. Thus (8 & 4) is (0b00001000 bitand 0b00000100) (using a binary notation that does not exist in standard C, for clarity), which results in 0b00000000 or 0.
The && operator performs a logical and operation on its boolean operands, producing a boolean result. Thus (8 && 4) is equivalent to ((8 != 0) and (4 != 0)), or (true and true), which results in true.
&& (logical and operator) - The left and right operands are boolean expressions. If both the operands are non-zero, then the condition becomes true.
>
& (bitwise and operator) - The left and right operands are integral types. Binary AND Operator copies a bit to the result if it exists in both operands.
In your teacher's example a && b, the left operand 4 and the right operand 8 are both non-zero. So the condition will become true.
In your teacher's other example a & b, the left operand 4 or 0100 and the right operand 8 or 01000 copies no bits to the result. This is because there are no common set bits in either operand.
& is bitwise operator and, && is logical for example if you use two number and you want to use bitwise operator you can write & .
if you want to use to phrase and you want to treat them logically you can use && .
I don't know if anyone could kindly explain this code for me?
unsigned int x = 0;
(x ^= x ) || x++ || ++x || x++;
printf("%d\n", x);
when I compile this on my computer using gcc 4.2, the output is 2.
Originally i thought maybe this behavior is unspecified but then i figure || will have lower precedence over other operators, so shouldn't the answer be 3? Since there are three "++".
Can someone explain? Thanks
(x ^= x) is evaluated and it yields 0, therefore:
(x++) is evaluated and it yields 0, therefore:
(++x) is evaluated and it yields 2, therefore it stops
It all boils down to one rule: || only evaluates its right side if its left side is false.
The issue is that the || operator is short-circuiting. As soon as it finds a true value, it no longer needs to check the remaining || statements; the answer is already known.
(x ^= x) evaluates to 0.
x++ evaluates to 0, then increments x to 1.
++x evaluates to 2 -- true.
The final or statement does not need to be computed. It "short-circuits" and immediately returns true.
The behaviour is well-defined. You are observing the short-circuiting behaviour of ||; the final x++ is never evaluated.
That is short-circuit semantics in action. The first expression x ^= x evaluates to 0, the second evaluates to 0 as well. The third one evaluates to 2, and then the logical expression is short-circuited since its result its already determined to be true.
Of course you shouldn't use such constructs, but let us analyze the expression.
There are 4 expressions combined with shortcut-OR:
a || b || c || d
b, c and d are only evaluated, if a is false, c and d only if b is false too, and d only if all from the before are false.
Ints are evaluated as 0 == false, everything else is not false.
x ^= 0
with x being 0 is 0 again.
x++
is evaluated and later increased, so it evaluates to 0, which invokes expression c, but later x will be increased.
++x
is first incremented, leading to 1, and then evaluated (leading to 1) which is the reason, why d is not evaluated, but the increment of b is pending, so we get 2.
But I'm not sure, whether such behaviour is exactly defined and leads to the same result on all compilers.
Avoid it.
The expressions between the || operators will be evaluated left to right until one is true:
(x ^= x )
Sets all bits in x to 0/off. (false);
x++
Increments x, it's now 1, but still false because this was a post increment.
++x
(pre-)Increments x, which is now 2 and also true, so there is no need for the right hand side of || to be evaluated.