Почему он отличается между -2147483648 и (int)-2147483648
когда я запускаю следующий код под Windows7 x64, скомпилированный с GCC MinGW, результат, кажется, переполнен:
cout<<-2147483648 ; //Output: 2147483648
но когда я назначил его целочисленной переменной или просто преобразовать его в тип int:
cout<<(int)-2147483648 ; //Output: -2147483648
Итак, что не так с предыдущей версией моего кода? Смнсс не типа int? или что такое нижняя граница целого числа? Большое спасибо.
4 ответов
2147483648 не вписывается в int или long в вашей системе, поэтому он рассматривается как константа типа unsigned long. (Edit: как указал ouah в комментариях, это неопределенное поведение в стандартном C++, но ваш компилятор принимает его как расширение.) Отрицание целочисленного значения без знака возможно, но приводит к другому целочисленному значению без знака, никогда отрицательному числу. Отрицание 2147483648UL производит 2147483648UL (предполагая, как и в вашей системе, что unsigned long-это 32 бит тип.)
бросая это в int
производит результат, определенный реализацией, обычно результат, который вы видите, но не обязательно. Вы можете получить нужный результат без каких-либо преобразований, написав -2147483647 - 1.
Итак, что случилось с предыдущей версии моего кода?
предположительно, вы используете компилятор до 2011 года, и в вашей системе long
имеет 32 бита. Значение (-231) не гарантированно вписывается в long
, поэтому он может переполниться. Это дает неопределенное поведение, поэтому вы можете видеть что угодно.
наиболее вероятное объяснение конкретного значения, которое вы видите (231) заключается в том, что при отсутствии определенного поведения в C++ ваш компилятор использует старые правила C90 и преобразует значение в unsigned long
.
Смнсс не типа int?
до 2011 года это было int
если значение представимо int
, иначе long
, с неопределенным поведением, если этого недостаточно. C++11 добавляет long long
тип и позволяет использовать его для целочисленных литералов, если long
недостаточно большой.
или что такое нижняя граница целого числа точно?
целочисленные типы со знаком с N битами имеют диапазон не менее -2(N-1)+1 к 2(N-1)-1. Ваше значение -231, что находится вне диапазона для 32-разрядного типа.
язык не указывает точный размер целочисленных типов; просто это int
должно быть не менее 16 бит,long
не менее 32, и (с 2011 года) long long
не менее 64.
прежде всего, важно понять, что нет отрицательных целых литералов.
другие объяснили, почему конкретный компилятор OP ведет себя так, как он делает. Но для записи, это то, что компилятор должны do, между строк, на 32-разрядной системе:
- у вас есть номер 2147483648, который не может поместиться в 32-битный подписанный
int
формата дополнения two. - так как это десятичный число (без U, L или подобного суффикса) компилятор проверяет свою внутреннюю таблицу типов (1) на наличие такой целочисленной константы. Он работает следующим образом: попробуйте поместить его в
int
, если он не подходит, попробуйтеlong
, если он тоже не подходит, попробуйтеlong long
, если он тоже не подходит, у нас есть неопределенное поведение. Компилятор C или c++, следующий последнему стандарту, будет не попытайтесь поместить его в неподписанные типы. - в этом конкретном случае номер не вписывается в
int
иlong
, поэтому компилятор решает использоватьlong long
тип для литерала. - затем вы используете унарный оператор минус на этом литерале, заканчивая числом -2147483648. По иронии судьбы это вписывается в подписанный int формата дополнения two, но слишком поздно менять тип, компилятор уже выбрал
long long
как тип.
(1) эта "внутренняя таблица" выглядит иначе, если у вас есть суффикс без знака или если у вас есть шестнадцатеричный формат и т. д. Если есть суффикс без знака, он будет проверять только, соответствует ли число неподписанным числам. Если есть шестнадцатеричная нотация (но нет суффикса), она будет проверять int, затем unsigned int, затем long и так далее.
на самом деле я нашел объяснение из pdf-файла CS:APP, который отлично дает решение, вы можете скачать его здесь. http://www.csapp.cs.cmu.edu/public/waside/waside-tmin.pdf