-2147483648 - это наименьшее целое число для целочисленного типа с 32 битами, но кажется, что оно будет переполнено в if(...)
предложении:
if (-2147483648 > 0)
std::cout << "true";
else
std::cout << "false";
Это напечатает true
в моем тестировании. Однако, если мы приведем -2147483648 к целому числу, результат будет другим:
if (int(-2147483648) > 0)
std::cout << "true";
else
std::cout << "false";
Это напечатает false
.
Я запутался. Кто-нибудь может дать объяснение по этому поводу?
Обновление 02-05-2012:
Спасибо за ваши комментарии, в моем компиляторе размер int составляет 4 байта. Я использую VC для простого тестирования. Я изменил описание в моем вопросе.
Это очень много хороших ответов в этом посте. AndreyT дал очень подробное объяснение того, как компилятор будет вести себя при таком вводе, и как реализовано это минимальное целое число. qPCR4vir, с другой стороны, дал некоторые связанные «курьезы» и то, как представлены целые числа. Так впечатляет!
источник
INT_MIN
о-9223372036854775808
, еслиCHAR_BIT
есть 16. И дажеCHAR_BIT == 8
иsizeof(int
== 4) `вы можете получить ,-9223372036854775807
потому что C не требуется 2-комплемента номера.Ответы:
-2147483648
это не "число". Язык C ++ не поддерживает отрицательные литеральные значения.-2147483648
на самом деле выражение: положительное буквальное значение2147483648
с унарным-
оператором перед ним. Значение2147483648
слишком велико для положительной стороныint
диапазона на вашей платформе. Если типlong int
имеет больший диапазон на вашей платформе, компилятор должен будет автоматически предположить, что он2147483648
имеетlong int
тип. (В C ++ 11 компилятору также придется учитыватьlong long int
тип.) Это заставит компилятор вычислять-2147483648
в области большего типа, и результат будет отрицательным, как и следовало ожидать.Однако, по-видимому, в вашем случае диапазон
long int
совпадает с диапазономint
, и в целом нет целочисленного типа с большим диапазоном, чемint
на вашей платформе. Формально это означает, что положительная константа2147483648
переполняет все доступные целочисленные типы со знаком, что, в свою очередь, означает, что поведение вашей программы не определено. (Немного странно, что спецификация языка в таких случаях выбирает неопределенное поведение, вместо того, чтобы требовать диагностическое сообщение, но это так.)На практике, принимая во внимание, что поведение не определено,
2147483648
может интерпретироваться как некое зависящее от реализации отрицательное значение, которое становится положительным после-
применения к нему унарного кода. Альтернативно, некоторые реализации могут решить попытаться использовать неподписанные типы для представления значения (например, в C89 / 90 компиляторы должны были использоватьсяunsigned long int
, но не в C99 или C ++). Реализациям разрешено делать что угодно, поскольку поведение в любом случае не определено.В качестве примечания, это причина, почему такие константы, как
INT_MIN
правило, определяются каквместо, казалось бы, более простой
Последний не будет работать как задумано.
источник
#define INT_MIN (-2147483647 - 1)
.int
. Реализация OP может не иметь 64-битного типа.-1.0
это анализируется как отрицательное двойное значение, не так ли?unsigned long int
в этом контексте, но в C99 это разрешение было удалено. Обязательные литералы в C и C ++ должны иметь подписанные типы. Если вы видите здесь беззнаковый тип, когда подписанный будет работать, это означает, что ваш компилятор не работает. Если вы видите здесь неподписанный тип, когда никакой подписанный тип не будет работать, то это просто конкретное проявление неопределенного поведения.Компилятор (VC2012) повышает до "минимальных" целых чисел, которые могут содержать значения. В первом случае
signed int
(иlong int
) не может (до применения знака), ноunsigned int
может:2147483648
имеетunsigned int
???? тип. Во втором вы вынуждаетеint
отunsigned
.Здесь связаны "курьезы":
Стандарт C ++ 11 :
...
...
И это правила продвижения для целых чисел в стандарте.
источник
int
,long int
,unsigned long int
чтобы представлять unsuffixed десятичных констант. Это был единственный язык, который позволял использовать неподписанные типы для нефиксированных десятичных констант. В C ++ 98 это былоint
илиlong int
. Не допускается использование неподписанных типов. Ни C (начиная с C99), ни C ++ не позволяют компилятору использовать неподписанные типы в этом контексте. Ваш компилятор, конечно, может свободно использовать неподписанные типы, если ни один из подписанных не работает, но это все еще лишь конкретное проявление неопределенного поведения.int
илиlong int
представлять2147483648
. Также, AFAIK, в VC2012 обаint
иlong int
32-битные типы. Это означает, что в VC2012 литерал2147483648
должен вести к неопределенному поведению . Когда поведение не определено, компилятору разрешено делать все что угодно. Это будет означать, что VC2012 не сломан. Он просто выдал вводящее в заблуждение диагностическое сообщение. Вместо того, чтобы говорить вам, что поведение не определено, он решил использовать тип без знака.long
, и не требует выдачи диагностики? Это казалось бы сломанным.Короче говоря,
2147483648
переполняет-2147483648
, и(-(-2147483648) > 0)
естьtrue
.Это то , как
2147483648
выглядит в двоичной форме .Кроме того, в случае двоичных вычислений со знаком наиболее значимым битом («MSB») является знаковый бит. Этот вопрос может помочь объяснить почему.
источник
Поскольку
-2147483648
на самом деле к нему применяется2147483648
negation (-
), число не соответствует ожидаемому. На самом деле это эквивалент этого псевдокода:operator -(2147483648)
Теперь, если предположить, что ваш компилятор
sizeof(int)
равен4
иCHAR_BIT
определен как8
, это сделает2147483648
переполнение максимальным знаковым значением целого числа (2147483647
). Так какой же максимум плюс один? Давайте разберемся с 4-битным целым числом комплимента 2s.Подождите! 8 переполняет целое число! Что мы делаем? Используйте его беззнаковое представление
1000
и интерпретируйте биты как целое число со знаком. Это представление оставляет нам-8
применение отрицания дополнения 2s8
, которое, как мы все знаем, больше, чем0
.Вот почему
<limits.h>
(и<climits>
) обычно определяютINT_MIN
как((-2147483647) - 1)
- так, что максимальное целое число со знаком (0x7FFFFFFF
) отрицается (0x80000001
), а затем уменьшается (0x80000000
).источник
-8
прежнему-8
.-(8)
что в C ++ - это то же самое,-8
что отрицание применяется к литералу, а не к отрицательному литералу. Литерал is8
, который не помещается в 4-разрядное целое число со знаком, поэтому он должен быть без знака. Шаблон есть1000
. Пока ваш ответ правильный. Отрицание дополнения к двум1000
в 4 битах1000
, не имеет значения, подписано оно или нет. Ваш ответ гласит: «интерпретируйте биты как целое число со знаком», которое задает значение-8
после отрицания дополнения к двум, как это было до отрицания.8
. Отрицание применяется (по модулю 16), в результате чего окончательный ответ8
. Кодировка все еще 1000, но значение отличается, потому что был выбран тип без знака.