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