Будет ли такая оптимизация правильной, будет зависеть от того, что, если что-либо, реализация гарантирует о последствиях целочисленного переполнения:
- Если реализация гарантирует, что целочисленные сложения и умножения всегда будут вести себя так, как если бы они были выполнены со значениями, достаточно большими, чтобы удерживать результат, а затем два дополнения, усеченных до размера типа после каждой операции, замена
x*(m*a)/(m*b)
на x*a/b
нарушит такие гарантии. - Если реализация гарантирует, что целочисленное сложение и умножение всегда будет вести себя так, как если бы они давали какое-то число, но не гарантирует, что временные значения будут усечены до любого конкретного размера, такая оптимизация будет допустимой.
- Если реализация ничего не гарантирует о последствиях переполнения, и требует, чтобы программисты избегали их любой ценой, потому что они могут вызывать ошибочное поведение даже в тех частях программы, которые не используют результат, такая оптимизация будет b e действителен.
Компилятор g cc предлагает варианты, чтобы либо поддержать вариант сильной гарантии № 1, либо воздержаться от предоставления каких-либо гарантий, а также возможность целочисленного переполнения, нарушающего части кода, которые не используйте результат не только теоретический. Поскольку вариант №3 был бы безрассудно опасен для программ, которые будут получать ввод из потенциально ненадежных источников, и поскольку g cc не предлагает никаких настроек между №1 и №3, многие программы, включая те, где вариант №2 соответствовал бы требования, создаются с помощью флага fwrapv
, который принудительно устанавливает вариант №1.