Одновременное выполнение и если и еще блоки

В C или C++

if ( x )
    statement1;
else
    statement2;

Поскольку, что значение x оба оператора будут выполняться?

Я знаю, что мы можем выполниться if-else вместе как это:

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

Есть ли какой-либо путь, как значение? (Который я думаю, не возможно. Выяснение, потому что кто-то спорит!)

6
задан Spikatrix 15 February 2016 в 14:21
поделиться

12 ответов

для какого значения x будут выполняться оба оператора?

Такого значения нет: либо значение оценивается как true (что-то! = 0 ), или он оценивается как ложь ) (0). Других возможных значений не существует.

Я знаю, что мы можем выполнить if-else вместе следующим образом: if (1) {goto ELSE; } else {ELSE:}

Это работает, но совершенно не зависит от значения условия if .

15
ответ дан 8 December 2019 в 02:09
поделиться

для какого значения x будут выполняться оба оператора ??

Только в этом случае (в unix-подобных системах):

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

В этом случае обе ветви всегда будут вызываться одновременно (ну, более или менее одновременно), но в разных процессах.

Я знаю, что мы можем выполнить if-else вместе вот так:

Это:

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

- неправильная конструкция. Вместо этого вам нужно использовать что-то вроде этого:

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

Если всегда вызывается одна ветвь, то вам не нужно "else".

24
ответ дан 8 December 2019 в 02:09
поделиться

Вы можете использовать целое число в качестве тестовой переменной и проверять его значение с помощью>, <,> =, <=, ==

    int x = 0;

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

В этом примере оба оператора выполняются, только если x равен 0. Иначе будет только один из них.

0
ответ дан 8 December 2019 в 02:09
поделиться

Не существует единственного значения для x , для которого будут выполняться все пути условного оператора (что является своего рода точкой условного оператора. ; вы хотите выполнить одну ветвь или , другую на основе x ).

Однако ...

В C (и C ++) вы можете использовать средство setjmp / longjmp для выполнения обоих путей 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;
}

Первоначальный вызов setjmp возвращает 0, поэтому выполняется первая ветвь. Вызов longjmp раскручивает стек обратно до точки, откуда возвращается вызов setjmp , но на этот раз возвращаемое значение равно 1 (второй аргумент для longjmp ) , поэтому берется вторая ветвь. Однако это не то же самое, что статус , оцениваемый одновременно как 0 и не 0.

На практике это похоже на запись

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

, хотя семантика иная.

Вы, вероятно, могли бы сделать что-то подобное в C ++ с исключениями, но я недостаточно эксперт по C ++, чтобы сказать наверняка.

0
ответ дан 8 December 2019 в 02:09
поделиться

Нет, без хитрых уловок это невозможно. Подумайте, что означает выражение:

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

Здесь говорится, что нужно выполнить ifTrue , если cond истинно (ненулевое значение / true ), и выполнить ifFalse if cond ложно (ноль / ложь ). Поскольку cond не может быть одновременно истинным и ложным, вы не можете выполнить оба ifTrue и ifFalse без особого случая, например goto .

0
ответ дан 8 December 2019 в 02:09
поделиться

Вот простой пример:

#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;
}

Печать

Divisible by two

НЕ

Divisible by two
Divisible by three
-1
ответ дан 8 December 2019 в 02:09
поделиться

В рекурсивной функции могут выполняться обе ветви:

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

Вызов ее с помощью

recursive(true)

выполнит ветвь if, за которой следует ветвь else

2
ответ дан 8 December 2019 в 02:09
поделиться

Если это вопрос с подвохом, вы можете ответить с помощью

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

Использование выражений операторов GCC :) Для операторов выражений есть оператор запятой

if(expr2, 1) 
  expr1;
else
  expr2;

. Это довольно популярный вопрос .

0
ответ дан 8 December 2019 в 02:09
поделиться

Для случаев с одним оператором будет выполняться только один из них, а не оба. Это определение , если .

ОДНАКО , в случае оператора if , использующего составные операторы (также известные как блок операторов), компилятор может оптимизировать код для перехода от операторов then в дубликаты. операторы в блоке else .

Пример:

#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;
}

В приведенном выше примере компилятор может сгенерировать код так, чтобы при условии истина выполнялась первая инструкция в блоке истина , затем выполнение переходит к общим операторам в блоке else .

Компилятор переписывает код:

  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;

Это может произойти, если компилятор обнаружит повторяющиеся операторы в конце блока операторов для обоих условий.

0
ответ дан 8 December 2019 в 02:09
поделиться
switch ( x ) {
default: // if ( x )
  // stuff
  // no break
case 0: // else
  // more stuff
  break;
}

или более простой

if ( x ) {
  // stuff
}
// more stuff
0
ответ дан 8 December 2019 в 02:09
поделиться

Если вы не возражаете против неопределенного поведения, вы можете сделать это в 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";
  }
}

Это отлично работает с GCC и Clang. Он работает, вызывая setjmp в буфере в b.j.b . Этот буфер хранится в оболочке в классе, потому что это может быть массив, а массивы могут быть скопированы только в том случае, если они завернуты в класс. Конструктор backer затем принимает возвращаемое значение setjmp и инициализирует с ним did . В деструкторе backer этот флаг проверяется, и если он ложный (первый возврат setjmp ), он возвращается назад и позволяет setjmp вернуть ненулевое значение. . Деструктор backer вызывается, когда заканчивается одна из ветвей.

Компилятор может скопировать объект backer , созданный при инициализации b . Если это произойдет, его конструктор копирования позаботится о настройке did на true , гарантируя, что мы вернемся назад только один раз, даже если компилятор не оптимизировал поддержку . копировать во время инициализации.

Таким образом, программа печатает ab .

4
ответ дан 8 December 2019 в 02:09
поделиться

Во-первых, это не глупый вопрос :)

Чтобы понять, почему вы не можете сделать это с помощью особых ухищрений, нам нужно сделать шаг вниз к сборке, которая генерируется if-выражением (в частности, сборка для процессора Intel с gcc 4.2.1 - на разных архитектурах будет другая сборка).

Возьмем эту простую программу на C:

#include <stdio.h>

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

Если пользователь вводит ненулевое целое число, мы возвращаем 100; в противном случае мы возвращаем 3. Фактическое условие здесь не имеет значения, потому что нас интересует только ассемблер, сгенерированный для 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

Я собираюсь предположить, что вы не знаете ассемблера - но не волнуйтесь, этот пример не так уж сложен для понимания. Здесь происходит следующее: мы вызываем scanf, и сравниваем результат (i) с 8.

Далее происходит Jump if Not Equal инструкция к метке L2. Это означает, что если i равно 8, то выполняются следующие инструкции:

  • Move 3 into rbp
  • Move rbp into eax
  • Leave (тем самым возвращая значение 3 из программы).

Однако, если i не равно 8, то при выполнении инструкции jne мы не переходим. Вместо этого мы:

  • Перемещаем 100 в rbp
  • Jump безусловно на метку L4
  • Перемещаем rbp в eax и в итоге возвращаем 100 из программы.

В ассемблере, сгенерированном здесь, есть только два возможных ответвления. Вы не можете произвольно переупорядочить код.

Так можно ли выполнить обе ветви (когда они не являются операторами return)? Да, при условии, что ваш компилятор не способен корректно создавать ветвящийся код. Но это никогда не произойдет на компиляторе производственного уровня.

2
ответ дан 8 December 2019 в 02:09
поделиться