2015-06-10 4 views
4

Я знаю, что если за номером следует U-суффикс, он обрабатывается как unsigned. Но почему следующая программа печатает правильное значение переменной i, даже если оно инициализируется отрицательным значением. (Составлено с GCC 4.9.2, 4.8.2, 4.7.1 &)U суффикс в объявлении переменной

Program1.cpp

#include <iostream> 
int main() 
{ 
    int i=-5U; 
    std::cout<<i; // prints -5 on gcc 4.9.2, 4.8.2, & 4.7.1 
} 

Program2.cpp

#include <iostream> 
int main() 
{ 
    auto i=-5U; 
    std::cout<<i; // prints large positive number as output 
} 

Но если я использую автоматическое ключевое слово (Тип deducer new C++ 0x), он дает мне большое положительное число, как ожидалось.

Пожалуйста, исправьте меня, если я что-то неправильно понимаю.

+1

Если бы я должен был догадаться, я бы сказал, что число, которое вы получаете, будет чем-то вроде линий (2^32) -5, что составляет 4 294 967 261. Правильно? –

+0

@AlexZywicki: правый !!! – Destructor

ответ

11

-5U не является -5 U. Это -(5U). Знак минус - оператор отрицания, действующий на 5U, а не первый символ целочисленного литерала.

Когда вы отрицаете число без знака, это эквивалентно вычитанию текущего значения из 2^n, где n - это количество бит в целочисленном типе. Так что это объясняет вторую программу. Что касается первого, когда вы передаете целое число без знака в целое число со знаком (как вы это делаете, назначив его int), если значение вне диапазона, результатом является неопределенное поведение, но в целом * приведет к тому, что значение будет переинтерпретируется как целое без знака - и так как беззнаковое отрицание, как раз так, имеет такое же поведение, что и отрицательное знаком, подписанное двумя, результат такой же, как если бы отрицание произошло в подписанном контексте.

. * Примечание. Это НЕ одна из тех ситуаций, которые были «неопределенным поведением», которые относятся только к академическим интересам к лакомым языкам. Компиляторы могут и предполагают, что приведение неподписанного числа к подписанному не приведет к переполнению (особенно, когда результирующее целое затем используется в цикле), и есть известные примеры этого предположения, превращающие небрежно написанный код в багги-программы.

+1

Подписанное целочисленное переполнение - это неопределенное поведение, а не реализация. – edmz

+0

@black Хороший улов. – Sneftel

+0

@Sneftel: так почему _implicit conversion_ от 'unsigned' до' signed' не встречается во 2-й программе? – Destructor