2017-02-08 5 views
1

При оптимизации, GCC иногда говорит мнеПочему может произойти переполнение подписей при смене деления на сдвиг вправо?

предполагая, подписанное переполнение не происходит при упрощении / или % к >> или &
[-Wstrict-overflow]

я не смог сделать воспроизводимый тест-случай для этого, но в моем производственном коде есть что-то вроде

int left = a.left() + (a.width() - b.width())/2; 

, где все методы возвращают значения int.

Почему может замена компилятора из /2 с >>1 или (например) %4 с &3 приводят к целому перелива?

+0

>> на целых знаках, зависящих от реализации. См.: Http://stackoverflow.com/questions/11644362/are-the-results-of-bitwise-operations-on-signed-integers-defined – virgesmith

+0

Я думаю, что неправильно понял предупреждение, что результат может быть ** неопределенным **. Но это просто говорит нам о том, что это ** определено реализацией **. Это не так уж плохо - но все же полезно быть предупрежденным. –

+1

Обратите внимание, что это отличается от * программиста *, заменяя '/' на '>>', например, поскольку компилятор должен знать, для чего он предназначен. –

ответ

1

Сдвиг нового бита в бит знака приводит к непредвиденным результатам: 1001 (знак десятичной: 7) >> 1 результат в: 0100 (знак десятичной: 4). По крайней мере, с реализациями с использованием двух дополнений, которые составляют большинство.

Редактирование: на x86, однако, имеются инструкции сдвига, которые сохраняют бит знака.

+0

Последний раз, когда я проверил, двоичный код 1001 был десятичным 9 и 9/2 == 4. Учитывая, что компилятор знает, что аргументы являются (подписанными) целыми числами, я ожидаю, что он (а) будет использовать (или эмулировать) подписанный сдвиг вправо или (б) пропустить это упрощение, если он знает, что это необоснованно. –

Смежные вопросы