LINUX.ORG.RU

История изменений

Исправление 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 для знаковой арифметики. Тогда компилятор может считать, будто никаких переполнений в коде никогда не бывает.