Short circuiting if statement - c

Say you have this nested if-statement:
int *x;
int y;
if (x == NULL || y > 5)
{
if (x != NULL)
// this should print if x != NULL and y > 5
printf("Hello!\n");
// this should only print if x == NULL.
printf("Goodbye!\n");
}
return 0;
Here, if either statement is true, it will return the same value (0). We should only print "Goodbye" if the left side of the outside if statement is true, regardless of whether the right hand side is true or false. Is it possible to eliminate the inside if-statement by short-circuiting, turning this into a single if-statement?

If I have understood correctly what you need is the following
if ( x == NULL )
{
printf("Goodbye!\n");
}
else if ( y > 5 )
{
printf("Hello!\n");
}
Otherwise if the first compound statement includes other statements that have to be executed in case when x == NULL or y > 5 then the if statements can look like
if ( x == NULL || y > 5)
{
// common statements that have to be executed when x == NULL or y > 5
//...
if ( !x )
{
printf("Goodbye!\n");
}
else
{
printf("Hello!\n");
}
}

This will only print Goodbye if x is NULL and y > 5
if (x == NULL || y > 5)
{
if (x != NULL)
// this should print if x != NULL and y > 5
printf("Hello!\n");
else
// this should only print if x == NULL.
printf("Goodbye!\n");
}

Related

How to simplify if statements

How can I simplify below if statements?, I'm trying to achieve the possibly most efficient code.
// doSomething based on x value and y value
void doSomething(x int, y int) {
//x not zero and y not zero
if (x != 0 && y != 0) {
//do a
//do b if x greater or equal y
//else do c
if (x >= y) {
//do b
} else (x < y) {
//do c
}
return;
}
//do b if x not zero and y zero
if (x != 0 && y == 0) {
//do b
return;
}
//do e if both x and y zero
if (x == 0 && y == 0) {
//do e
return;
}
}
What is the most concise and efficient way to simplify?
As it stands, your code is equivalent to:
if (x == 0)
{
if (y == 0)
do e
}
else if (y != 0)
{
if (x < y)
do a,c
else
do a,b
}
In particular:
if x=0 && y!=0 or y=0 && x!=0, then do nothing;
the two branches //do b if x not zero and y zero and //do d if x zero and y not zero are unreachable in your code.
History:
The code in the question was changed several times. This answer is based on the original version of the code. That code is shown below, minimally modified so that it's compilable C code:
void original(int x, int y)
{
if (x == y && x != 0 && y != 0) {
// do a
// do b
return;
}
if (x < y && x != 0 && y != 0) {
// do a
// do c
return;
}
if (x > y && x != 0 && y != 0) {
// do a
// do b
return;
}
if (x != 0 && y == 0) {
// do a
// do b
return;
}
if (x == 0 && y != 0) {
// do a
// do d
return;
}
if (x == 0 && y == 0) {
// do e
return;
}
}
Motivation:
The advantage of the original code is that it clearly covers all possible input combinations.
The first three if statements handle the cases where x and y are non-zero (with x==y, x<y, and x>y handled separately). Then the remaining three if statements handle the cases where one or both are zero. That covers everything.
The disadvantages of the original code are:
Many of the comparisons are repeated several times, e.g. y != 0 is checked four times. Given that branching statements tend to be time consuming in contemporary (year 2021) processors, redundant comparisons are something to be avoided 1.
The code violates the DRY principle. Specifically, do a appears in five locations, and do b appears in three locations. So any refactoring of the code should attempt to eliminate the repetition.
1) The optimizer may be able reduce the number of comparisons. However, that's hard to test without real code.
Refactoring with nested if statements:
If we focus on the DRY principle first, we notice that a appears in 5 of 6 code blocks. Only the case for e doesn't invoke a. So the logical choice is to handle e first. This results in the following code structure:
if (x == 0 && y == 0) {
// do e
} else {
// do a
// everything else (note that either x is not zero, or y is not zero)
}
Within the "everything else", we have do b three times, do c once, and do d once. So the next step is to handle c and d, leaving only b. The refactored code looks like this:
void nestedIf(int x, int y)
{
if (x == 0 && y == 0) {
// do e
} else {
// do a
if (x == 0) {
// do d
} else {
if (y != 0 && x < y) {
// do c
} else {
// do b
}
}
}
}
Refactoring with early return statements:
Some coding standards insist that a function shall only return from one location. The nested if code meets that requirement, but at the cost of being a little messy due to nesting. Using early returns eliminates the nesting, and may allow the code for a thru e to be implemented inline without additional functions (assuming they're only a few lines each). The refactored code looks like this:
void earlyReturn(int x, int y)
{
if (x == 0 && y == 0) {
// do e
return;
}
// do a
if (x == 0) { // x is zero and y is not zero
// do d
return;
}
if (y != 0 && x < y) { // x and y are both not zero, and x < y
// do c
return;
}
// do b
}
assuming a(), b(), and e() have the same type (fxtype)
fxtype *fx[4] = { e, NULL, b, a }; // NULL when x==0, y!=0
fx[2*!!x + !!y](x, y);
Change a to include c() and b()
int a(int x, int y) {
// do previous a()
if (x < y) c(x, y); else b(x, y);
return 0;
}

How does 'if((x) || (y=z))' work?

I don't quite understand how the if statement in this case works. It evaluates the x != 0 statement and when that is not true anymore, it assigns z to y and then breaks the if statement?
int main()
{
int x, y, z, i;
x = 3;
y = 2;
z = 3;
for (i = 0; i < 10; i++) {
if ((x) || (y = z)) {
x--;
z--;
} else {
break;
}
}
printf("%d %d %d", x, y, z);
}
Let's decompose that into smaller bits.
if (x) is the same as if (x != 0). If x != 0, then you know the condition is true, so you don't do the other portion of the if.
If part 1. was false, then y = z assigns z into y and returns the final value of y.
From point 2., we can understand that if (y = z) is equivalent to y = z; if (y != 0)
Thus, from points 1. and 3., we can understand that :
if ((x) || (y = z)) {
doSomething();
}
else {
doSomethingElse();
}
Is the same as :
if (x != 0) {
doSomething();
}
else {
y = z;
if (y != 0) {
doSomething();
}
else {
doSomethingElse();
}
}
It's true it's not particularly readable code though.
No. if ((x) || (y = z)) {
in C-English is basically:
if x is nonzero, evaluate the following code.
if x is zero, set y to z.
if y is nonzero, evaluate the following code.
otherwise, break out of the loop.
If x is zero or y is zero, it breaks out of the loop.
int main()
{
int x = 3;
int y = 2;
int z = 3;
unsigned int i;
for (i = 0; i < 10; i++)
if (x != 0) {
x = x-1;
z = z-1;
}
else {
y = z;
if (y != 0) {
x = x-1;
z = z-1;
}
else {
break;
}
}
}
printf("%d %d %d", x, y, z);
}
In C, there is short-circuiting, so the statement y=z will not be evaluated until x becomes zero.
When x == 0, since z also decrements the same way, z == 0. Hence y will also be zero at that time due to the assignment. The statement y=z also returns y at this point which will be evaluated as a condition, and since that is also 0, the else break will be hit.
Hence I believe the answer should be 0 0 0.
When you use assignment in an if statement, the result of the assignment is returned. so when you write :
if (x = y)
It will be always true unless the value of y is 0, so 0 is returned as the result of assigning and the if statement is not executed.(anything except 0 is considered as true.)
So when you write :
if ( x || (x = y))
The if statement doesn't execute only if x is 0 & y is 0.
Here
if ((x) || (y = z))
there are two condition
one condition is
if ((x)) and another condition is if ((y = z))
if one of them is true then if portion is execute otherwise else condition work
only and only when both condition are false then else execute.

C Program output confusion

Can someone explain why the output of this program is false??
x && y gives 1. Still the output is false.
#include <stdio.h>
int main()
{
int x = 1, y = 2;
if(x && y == 1)
{
printf("true.");
}
else
{
printf("false.");
}
return 0;
}
Because == has a higher precedence than && So first this get's evaluated:
x && (y == 1)
y == 1 // 2 == 1
//Result: false
Which is false and then second:
x && false //1 && false
//Result: false
So the if statement will be false
For more information about operator precedence see here: http://en.cppreference.com/w/cpp/language/operator_precedence
if(x && y == 1)
Is the same as
if( ( x != 0 ) && ( y == 1 ) )
Here,x != 0 is true, but y == 1 is false. And since at least one of the operands of && is false, the condition evaluates to false and the else part executes.
It clearly stated X = 1 & Y = 2;
Now with your expression
X && Y == 1
The expression is evaluated as
Y == 1 (Precedence Rule, Also output is False)
X != 0 (Its True)
Now && is Logical And Operator, so it evaluates to True only if both the parts in expression evaluates to True!!!
It's okay to false, then 2 and 2 and it is different from one.
What you're asking is whether both x and y both are worth 1. If this happens say true but false

C while loop logic ( y != ( 1 || 0) )

I have the below code to choose sin or cos to be integrated,
while( x !=1 || y !=(1||0) ){
printf("Sin (1) or Cos (0)?\n");
x = scanf("%d",&y);
_flushall();
if(y==1){
printf("Sin set\n");
}
else if(y==0){
printf("Cos set\n");
}
}
However the
y!= (1||0)
never evaluates to true for y == 0 , can someone explain what's wrong here? Thanks.
You need (y != 1 && y != 0) (or similar, it depends on what you really mean to express there). The || operator is being applied to the operands 1 and 0. Put another way, y != (1 || 0) means "Do (1 || 0) then do y != result".
You are attempting to effectively code directly Boolean algebra, and C doesn't accept it in the manner you've provided.
while( x !=1 || y !=(1||0) )
should be
while( (x!=1) || ( (y!=1) || (y!=0) ) )
Never underestimate the value of using excess parentheses in C. The optimizer will likely optimize the code to be more efficient anyways.
The part of code that generates this error evaluates as follows:
LHS (left hand side), RHS (right hand side)
LHS = y
!= (1||0) [definition given]
!= (1) [b/c (1||0) = (1)]
y != (0||1)
is equivalent to
y != 1
since 0||1 is 1. You'll need two comparisons if you want y != 0 or y != 1.

In C, does (x==y==z) behave as I'd expect?

Can I compare three variables like the following, instead of doing if((x==y)&&(y==z)&&(z=x))? [The if statement should execute if all three variables have the same value. These are booleans.]
if(debounceATnow == debounceATlast == debounceATlastlast)
{
debounceANew = debounceATnow;
}
else
{
debounceANew = debounceAOld;
}
No, it does not.
x == y is converted to int, yields 0 or 1, and the result is compared to z. So x==y==z will yield true if and only if (x is equal to y and z is 1) or (x is not equal to y and z is 0)
What you want to do is
if(x == y && x == z)
No. The equality check associates from the left and the logical result is compared as a number, so that the expression 2 == 2 == 1 parses as (2 == 2) == 1, which in turn gives 1 == 1 and results in 1, which is probably not what you want.
You can actually type something like this:
int main()
{
const int first = 27,
second = first,
third = second,
fourth = third;
if (!((first & second & third) ^ fourth))
return 1;
return 0;
}

Resources