Почему это отличается от -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 и т.д.