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