tags:

views:

610

answers:

12

In C or C++

if ( x )
    statement1;
else
    statement 2;

for what value of x both statements will be executed?? I know we can execute if-else together like this:

if(1){
    goto ELSE;
}
else{
    ELSE:
}

Is there any way, like a value? (Which i think is not possible. Asking because someone is arguing!)

+13  A: 

for what value of x both statements will be executed?

There is no such value: either the value evaluates to true (something != 0), or it evaluates to false) (0). No other possible values exist.

I know we can execute if-else together like this: if(1){ goto ELSE; } else{ ELSE: }

That works but it isn’t depending of the value of the if condition at all.

Konrad Rudolph
I don't know if C/C++ allows this but perhaps you should expand your first part of the answer to cover what happens if an expression could evaluate to both, for instance in C#, operator overloads could make a value correspond to both true and false, depending on the expression it was used in, but this still wouldn't lead to both branches executing.
Lasse V. Karlsen
fork() is the answer (see SigTerm's answer).
Paul Hankin
It's not possible to evaluate both statements without essentially removing the if, since there's no point in having an if if both the if and the else are executed- that's called regular code.
DeadMG
@Paul: how does `fork` change what I’ve said? Yes, it’s a pretty cute trick but it does not invalidate my statement.
Konrad Rudolph
Konrad Rudolph
+1 For not handing the really nasty code to the newbies :)
Basiclife
A: 

Without devious trickery, no, this is not possible. Consider what the expression means:

if (cond) {
  ifTrue;
} else {
  ifFalse;
}

This says to execute ifTrue if cond is true (a non-zero value/true), and to execute ifFalse if cond is false (zero/false). Since cond can't be simultaneously true and false, you can't execute both ifTrue and ifFalse without a special case, such as goto.

Antal S-Z
+20  A: 

for what value of x both statements will be executed??

Only in this case (on unix-like systems):

 pid_t  pid;
 pid = fork();
 if (pid == 0){
    //some code
 }
 else {
    //some code
 }

In this case both branches will be always called simultaineously (well, more or less simultaneously), but in different processes.

I know we can execute if-else together like this:

This:

if(1){
    goto ELSE;
}
else{
    ELSE:
}

is a wrong construct. You need to use something like this instead:

if ( condition) {
    //some code here
    ...
}
... //some other code here

If one branch is always called, then you don't need "else".

SigTerm
+1 for the fork()
Default
The fork is a nice trick, but does not really work with "one" value since the return value of fork() is zero for one and non zero for the other process.
josefx
The construct is only wrong though because there is a statement missing after `ELSE:`. If you replace it by `ELSE: ;` it becomes completely legal.
Johannes Schaub - litb
+1 for denoting the absurdity of using `goto` when it's clearly not needed...
Matthieu M.
There is a possibility that the `true` condition may execute code *common* to both statement blocks within the `else` statement block. This is the compiler refactoring the code. See my answer below.
Thomas Matthews
+1  A: 

In a recursive function both branches can be executed:

void recursive(bool first)
{
    if(first)
    {
        recursive(false);
    }
    else
    {
        //END
    }
}

Invoking it with

recursive(true)

will execute the if branch followed by the else branch

josefx
A: 

Here's a simple example:

#include <stdio.h>

int main() {
    int x;
    x = 6;
    if (x % 2 == 0) {
        printf("Divisible by two\n");
    }
    else if (x % 3 == 0) {
        printf("Divisible by three\n");
    }
    else {
        printf("Not divisible by two or three\n");
    }
    return 0;
}

Prints

Divisible by two

NOT

Divisible by two
Divisible by three
Umang
A: 

You can use an integer as test variable and check its value using >,<,>=,<=,==

    int x = 0;

    if ( x >= 0 ) {
        statement 1;
    }
    if ( x <= 0 ) {
        statement 2;
    }

In this example, both statements are only executed if x is 0. Otherwise only one of them will be.

Mat
+3  A: 

If you don't mind some undefined behavior, you can do it like this in C++:

struct J {
  jmp_buf b;
};

struct backer {
  backer(int v):did(v) { }

  backer(backer const& o):j(o.j),did(o.did) { 
    o.did = true; 
  }

  ~backer() {
    if(!did) {
      longjmp(j.b, 1);
    }
  }

  operator bool() {
    return !did;
  }

  J j;
  mutable bool did;
};

int main() {
  if(backer b = setjmp(b.j.b)) {
    std::cout << "a";
  } else {
    std::cout << "b";
  }
}

This works fine with GCC and Clang. It works by calling setjmp on the buffer in b.j.b. That buffer is kept wrapped in a class because it can be an array, and arrays can only be copied if they are wrapped in a class. backer's constructor then takes setjmp's return value and initializes did with it. In backer's destructor that flag is tested and if it's false (first return of setjmp), it jumps back and let setjmp return a non-zero value. The destructor of backer is called when one of the branches finish.

The compiler is free to copy the backer object constructed in initializing b. If that happens, the copy constructor of it cares about setting did to true, ensuring that we jump back only one time even if the compiler didn't optimize out the backer copy during initialization.

Thus the program prints ab.

Johannes Schaub - litb
That's different to the GOTO method how, precisely?
DeadMG
@DeadMG it doesn't change what the statement is. The Statements can be arbitrary. For the goto method, the statement has to have a goto at the end and the statement must be braced-enclosed as a result. So, the question asks "For what value x" but not "For what value x and what statements" - it doesn't allow changing the statements. The history of my answer shows that i first came up with an answer very similar to @John's current one - but i deleted it temporarily because i came to the conclusion it wasn't according to the rules :)
Johannes Schaub - litb
A: 

If it is a trick question, you could answer with

if( ({ statement2; 1; }) ) 
  statement1;
else
  statement2;

Using GCC statement expressions :) For expression statements, there is the comma operator

if(expr2, 1) 
  expr1;
else
  expr2;

This is a quite popular question.

Johannes Schaub - litb
+2  A: 

First off, this isn't a stupid question :)

To understand why you can't accomplish this with any special trickery, we need to step down to the assembly that gets generated by an if-statement (particularly, the assembly for an Intel processor with gcc 4.2.1 -- different architectures will result in different assembly).

Take this simple C program:

#include <stdio.h>

int main()
{
    int i;
    scanf("%d", &i);
    if (i == 8)
    {
        return 100;
    }
    else
    {
        return 3;
    }
}

If the user enters a non-zero integer, we return 100; otherwise we return 3. The actual condition doesn't really matter here, because we're only interested in the assembly generated for main:

        ; ...
        call    _scanf
        movl    -4(%rbp), %eax
        cmpl    $8, %eax
        jne     L2
        movl    $100, -20(%rbp)
        jmp     L4
L2:
        movl    $3, -20(%rbp)
L4:
        movl    -20(%rbp), %eax
        leave
        ret

I'm going to assume you have no knowledge of assembly -- but don't worry, this example isn't terribly hard to keep up with. What's happening here is that we call scanf, and we compare the result of it (i) with 8.

Next, there's a Jump if Not Equal instruction to the label L2. This means that if i is equal to 8, the following instructions executed are:

  • Move 3 into rbp
  • Move rbp into eax
  • Leave (thereby returning the value 3 from the program).

However, if i is not equal to 8, then when we hit the jne instruction, we don't jump. Instead, we:

  • Move 100 into rbp
  • Jump unconditionally to the label L4
  • Move rbp into eax and end up returning 100 from the program.

With the assembly generated here, there are really only two possible branches. You can't arbitrarily reorder the code.

So would it be possible to execute both branches (when they aren't both return statements)? Yes, on the condition that your compiler is incapable of correctly producing branching code. But that would never happen on a production-level compiler.

Mark Rushakoff
I note that in your example, there is no side-effect on the return statements. The compiler would avoid doing such "compute A ; r <- A ; compute B ; r<-B ; ret" path when A and B cannot be reduced to side-effect-free expressions.
sylvainulg
A: 

There is no single value for x for which all paths of a conditional statement will be executed (which is kind of the point of a conditional statement; you want to execute one branch or the other based on x).

However...

In C (and C++), you could use the setjmp/longjmp facility to execute both paths of an if-else:

#include <setjmp.h>
#include <stdio.h>

jmp_buf Env;

int main(void)
{
  int status = setjmp(Env);
  if (status == 0)
  {
    printf("In status == 0 branch\n");
    longjmp(Env,1);
  }
  else
  {
    printf("In status != 0 branch\n");
  }
  return 0;
}

The initial call to setjmp returns 0, so the first branch is taken. The call to longjmp unwinds the stack back to the point where the setjmp call returns, but this time the return value is 1 (the second argument to longjmp), so the second branch is taken. However, this is not the same thing as status evaluating to 0 and non-0 simultaneously.

In practice, it's similar to writing

for (status = 0; status < 2; status++)
{
  if (status == 0)
    printf("In status == 0 branch\n");
  else
    printf("In status != 0 branch\n");
}

although the semantics are different.

You could probably do something similarly ugly in C++ with exceptions, but I'm not enough of a C++ expert to say for sure.

John Bode
A: 

For single statement cases, only one of them will be executed, not both. This is the definition of if.

HOWEVER, in the case of an if statement using compound statements (a.k.a. statement block), the compiler may optimize the code to jump from the then statements into duplicate statements in the else block.

Example:

#include <iostream>
using namespace std;

int main(void)
{
  static const char common_text1[] = "Some common text here.\n";
  static const char common_text2[] = "Even more common code here.\n";
  if (true)
  {
     cout << "Condition is true.\n";
     cout << common_text1;  // Execution may jump to same line below.
     cout << common_text2;
  }
  else
  {
     cout << "\nCondition is false.\n";
     cout << common_text1;  // This line and the next may be executed when the
     cout << common_text2;  //   condition is true.
  }
  return 0;
}

In the above example, the compiler may generate code so that when the condition is true, the first statement in the true block is executed, then execution jumps to the common statements in the else block.

The compiler is rewriting the code:

  if (true)
  {
     cout << "Condition is true.\n";
  }
  else
  {
     cout << "\nCondition is false.\n";
  }

  // The compiler factored-out the common statements.
  cout << common_text1; 
  cout << common_text2;

This may happen when the compiler sees duplicate statements near the end of the statement block for both conditions.

Thomas Matthews
Note that few compilers are that clairvoyant. Also, this requires that the common part is truly common, including the destruction of block-scoped variables.
MSalters
A: 
switch ( x ) {
default: // if ( x )
  // stuff
  // no break
case 0: // else
  // more stuff
  break;
}

or the much simpler

if ( x ) {
  // stuff
}
// more stuff
drawnonward