Страницы

Поиск по вопросам

воскресенье, 8 декабря 2019 г.

Странное поведение при переполнении, зависящее от уровня оптимизации

#cpp


Возьмём код:

#include 

int main()
{
    unsigned char xi;
    unsigned char xf;
    int   bi = -300;
    float bf = -300;
    xi = bi;
    xf = bf;
    printf("xi = %d\n", xi);
    printf("xf = %d\n", xf);

    return 0;
}


получаем вывод:

xi = 212
xf = 0


хотя ожидалось, что unsigned char корректно переполнится и обе переменные окажутся
равны 212. Что интересно, при наличии флага -O0 (без оптимизации) получается вывод
как и ожидалось:

xi = 212
xf = 212


при флаге -O1 и выше уже появляется отличие.

По-видимому, я здесь наступил на какой-то вариант неопределённого поведения, подскажите,
что именно здесь произошло? Где косяк?

PS. При переполнии "вверх" на выводе получается 255, если через float пропустить,
как в примере.
    


Ответы

Ответ 1



Переполнение при целочисленном преобразовании в беззнаковый тип подчиняется правилам Integral conversions, т.е. обрабатывается как обычно, по правилам модульной арифметики. Переполнение при плавающем преобразовании в беззнаковый тип подчиняется правилам Floating-integral conversions - т.е. это неопределенное поведение. Вот и вся разница. Нет ничего "странного" в том, что проявления неопределенного поведения меняются в зависимости от настроек компилятора.

Ответ 2



Это неопределенное поведение. Тип назначения должен вмещать значение источника. см. [conv.fpint] The behavior is undefined if the truncated value cannot be represented in the destination type.

Комментариев нет:

Отправить комментарий