Порядок оценки: неопределенное поведение? или дефект компилятора?
Я получаю неправильный код asm для приведенного ниже тестового кода от компилятора C. Это связано с неопределенным поведением?
void SimulatedTest(void)
{
if ( (a) || (b && c || d) == 1 )
{
i = 2;
}
else
{
i = 4;
}
}
Какой стандарт говорит:
6.5.16 Операторы присваивания
Порядок оценки операндов не указан. Если предпринята попытка изменить результат оператора присваивания или получить к нему доступ после следующей точки последовательности, поведение не определено
Правило приоритета оператора C
- ()
- ==
- || &&
Для проблемного случая: 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 )
Но компилятор компилируется правильно. Просто не очень очевидно, что должно происходить с человеческим разумом.