2016-06-14 2 views
-2

Кажется, что компилятор MSVC обрабатывает подписанное и неподписанное переполнение differnetly. При выдаче двойного значения, превышающего максимальное целочисленное значение, результатом является наименьшее возможное целочисленное значение (всегда одно и то же). При отливке без знака int литье производит переполнение как ожидалось (максимальное значение unsigned int value + 1 производит 0, максимальное значение unsigned int + 2 производит 1, ...) Может кто-нибудь объяснить поведение компилятора, или это ошибка ?литье двойное к подписанному против целого числа без знака

Испытанные Составители MSVC 10 и 14

#define BOOST_TEST_MODULE Tests 
#include <boost/test/unit_test.hpp> 
#include <climits> 
#include <iostream> 
BOOST_AUTO_TEST_CASE(test_overflow_signed) { 
    double d_int_max_1 = INT_MAX + 1.; //2147483647 + 1 
    double d_int_max_2 = INT_MAX + 2.; //2147483647 + 2 

    BOOST_CHECK((int)(2147483648.) != (int)(2147483649.)); //succeeds (overflows to -2147483648 and -2147483647) 
    BOOST_CHECK((int)(d_int_max_1) != (int)(d_int_max_2)); //fails (both values overflow to -2147483648) 
    std::cout << "(int)(2147483648.) == " << (int)(2147483648.) << std::endl; //-2147483648 
    std::cout << "(int)(2147483649.) == " << (int)(2147483649.) << std::endl; //-2147483647 
    std::cout << "(int)(d_int_max_1) == " << (int)(d_int_max_1) << std::endl; //-2147483648 
    std::cout << "(int)(d_int_max_2) == " << (int)(d_int_max_2) << std::endl; //-2147483648 
} 

BOOST_AUTO_TEST_CASE(test_overflow_unsigned) { 
    double d_int_max_1 = UINT_MAX + 1.;//4294967295 + 1 
    double d_int_max_2 = UINT_MAX + 2.;//4294967295 + 2 
    //BOOST_CHECK((unsigned int)(4294967296.) != (unsigned int)(4294967297.)); //compiler fails (!= truncation of constant value) 
    BOOST_CHECK((unsigned int)(d_int_max_1) != (unsigned int)(d_int_max_2)); //succeeds (overflows to 0 and 1) 
    std::cout << "(unsigned int)(d_int_max_1) == " << (unsigned int)(d_int_max_1) << std::endl; //0 
    std::cout << "(unsigned int)(d_int_max_2) == " << (unsigned int)(d_int_max_2) << std::endl; //1 
} 
+2

«странное поведение» не является подходящим описанием проблемы. –

+0

Надеюсь, теперь вопрос ясен. – stefanjp

ответ

0

[conv.fpint]/1 prvalue типа с плавающей точкой могут быть преобразованы в prvalue целочисленного типа. Преобразование усекает; т. е. дробная часть отбрасывается. Поведение не определено, если урезанное значение не может быть , представленное в типе назначения.

Emphasis mine. Поскольку поведение не определено, любой исход будет правильным.

+0

спасибо за то, что вы разрешили мне mistery. не зная, что компилятор ведет себя по-разному для отливки плавающих значений в неподписанные и подписанные целочисленные типы, очень затрудняет отслеживание ошибки. – stefanjp

+0

Нет никакой разницы - поведение не определено в любом случае, независимо от того, используете ли вы 'int' или' unsigned'. –

+0

реализованное поведение компилятора msvc отличается. unsigned int overflows, подписанный int устанавливается в INT_MIN в случае отливки слишком большого значения. – stefanjp

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