История изменений
Исправление wandrien, (текущая версия) :
Возьмём такой пример на Си-подобном псевдоязыке:
void f(integer x)
{
integer a = 1;
while (a <= 10) {
print(a * x);
a++;
}
}
От Си наш воображаемый язык отличается тем, что integer
здесь это целые числа в математическом смысле. (Предположим, что там под капотом используется куча, и пока ОЗУ хватает, мы можем числа любой длины вычислять.)
Перепишем теперь этот код, чтобы избавиться от 10 умножений и заменить на более эффективные сложения:
void f(integer x)
{
integer a = x;
integer limit = x * 10;
while (a <= limit) {
print(a);
a += x;
}
}
Результат исполнения программы будет идентичен. Эти алгоритмы эквивалентны.
Однако если мы переходим к числам с ограниченной разрядностью, то результаты работы программы не обязательно будут экивалентны. Поэтому делать такую трансформацию компилятор не сможет для общего случая.
Вот необходимостью разрешить ему делать такие трансформации и оправдывают обычно наличие UB для знаковой арифметики. Тогда компилятор может считать, будто никаких переполнений в коде никогда не бывает.
Исходная версия wandrien, :
Возьмём такой пример на Си-подобном псевдоязыке:
void f(integer x)
{
integer a = 1;
while (a <= 10) {
print(a * x);
a++;
}
}
От Си наш воображаемый язык отличается тем, что integer
здесь это целые числа в математическом смысле. (Предположим, что там под капотом используется куча, и пока ОЗУ хватает, мы можем числа любой длины вычислять.)
Перепишем теперь этот код, чтобы избавиться от 10 умножений и заменить на более эффективные сложения:
void f(integer x)
{
integer a = x;
integer limit = x * 10;
while (a <= limit) {
print(a);
a += x;
}
}
Результат исполнения программы будет идентичен. Эти алгоритмы эквивалентны.
Однако если мы переходим к числам с ограниченной разрядностью, то результаты работы программы не обязательно будут экивалентны. Поэтому делать такую трансформацию компилятор не сможет для общего случая.
Вот необходимостью разрешить ему это делать такие трансформации и оправдывают обычно наличие UB для знаковой арифметики. Тогда компилятор может считать, будто никаких переполнений в коде никогда не бывает.