Порядок оценки: неопределенное поведение? или дефект компилятора?

Я получаю неправильный код asm для приведенного ниже тестового кода от компилятора C. Это связано с неопределенным поведением?

void SimulatedTest(void)
{                                   
    if ( (a) || (b && c || d) == 1 )
    {
        i = 2;
    }
    else
    {
        i = 4;
    }
}

Какой стандарт говорит:

6.5.16 Операторы присваивания

Порядок оценки операндов не указан. Если предпринята попытка изменить результат оператора присваивания или получить к нему доступ после следующей точки последовательности, поведение не определено

Правило приоритета оператора C

  1. ()
  2. ==
  3. || &&

Для проблемного случая: if ( (a) || (b && c || d) == 1) Компилятор вычисляет выражение в следующем порядке и генерирует неправильный код

1.(b && c || d) -> R1

2.R1 == 1 -> R2

3. (а) || R2

Однако компилятор генерирует правильный код для следующих случаев

Дело1: Когда нет реляционной операции '=='

if ( (a) || (b && c || d) )//compiler generates expected code

Случай 2: когда скобки добавляются для логической операции ИЛИ

if ( ((a) || (b && c || d)) == 1 )//compiler generates expected code

Case3: между операциями не используются круглые скобки

if ( a || b && c || d == 1 )//compiler generates expected code

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

С Уважением,

макинтош

2 ответа

Оператор равенства == имеет более высокий приоритет, чем логический или || оператор. Поэтому компилятор корректен и не имеет неопределенного поведения.

Оценка идентична:

a || ( ( b && c || d ) == 1 )

Это:

 if ( (a) || (b && c || d) == 1 )

сравнивает результаты || с целым числом, которое никогда не является тем, что вы хотите сделать.

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

 if ( (a) || ((b && c) || d) == 1 )

или же

 if ( (a) || (b && (c || d)) == 1 )

иметь дело с && или же ||

и в зависимости от того, что вы ожидаете сравнить с == (если вы действительно хотите это сделать, в чем я сомневаюсь)

 if ( (a) || ((b && c || d) == 1) )

или же

 if ( ((a) || (b && c || d)) == 1 )

Но компилятор компилируется правильно. Просто не очень очевидно, что должно происходить с человеческим разумом.

Другие вопросы по тегам