подписано — C ++ Почему LLONG_MIN == -LLONG_MIN

В C ++, если я делаю это:

__int64 var = LLONG_MIN;
__int64 var2 = -var;
cout << "var: "<< var << endl;
cout << "var2: "<< var2 << endl;

Я получаю вывод:

var: -9223372036854775808
var2: -9223372036854775808

Какая часть стандарта охватывает это? Я предполагаю, что это целочисленное переполнение со знаком. Это было скомпилировано с использованием g ++ (GCC) 4.7.2.

У меня есть функция вычитания, и я пишу функцию добавления, и я подумал, что могу просто сделать это:
add( someobj &obj, long long num ) { subtract( obj, -num ); }, Я думаю, что это сработало бы, если бы не LLONG_MIN.

1

Решение

Это действительно целочисленное переполнение и артефакт дополнение двух.

На вашей реализации, LLONG_MIN является -9223372036854775808 который 0x8000000000000000 в шестнадцатеричном (я буду использовать это шестнадцатеричное обозначение, потому что легче увидеть, что происходит с битами).

Когда вы вычисляете -LLONG_MIN в системе, которая использует два дополнения, под капотом вы сначала делаете поразрядно-не 0x7FFFFFFFFFFFFFFF == LLONG_MAX) затем добавьте 1, которое переполняет целое число со знаком и возвращает 0x8000000000000000 == LLONG_MIN,

Обратите внимание, что целочисленное переполнение со знаком является неопределенным поведением, поэтому нет гарантии, что оно будет работать согласованно в каждой реализации C ++.

5

Другие решения

Хотя другой ответ правильный, я не думаю, что он объясняет интуитивную сторону этого:

LLONG_MIN ==  -2^63      == -9223372036854775808
LLONG_MAX ==   2^63 - 1  ==  9223372036854775807

Я пытался продумать использование LLONG_MIN как особого случая для чего-то, но потом я вспомнил, что с целочисленными типами со знаком c ++ самое низкое значение всегда на 1 больше, чем 0, чем самое высокое значение (забавно, каждый из них, от байт удваивается, заканчивается -...8 а также +...7!).

Итак, мне было любопытно, что бы произошло, если бы вы отрицали наименьшее значение, поскольку для него нет эквивалента в положительном мире; и, увы, это считается как целочисленное переполнение (-9223372036854775808 == 9223372036854775808 > 9223372036854775807) и, таким образом, переполняется на 1 (9223372036854775807 + 1), возвращая нас к … -9223372036854775808!


Код:

#include <iostream>
#include <climits>
using namespace std;

int main() {
long long l1 = LLONG_MIN;
long long l2 = -l1; //Equivalent to l1.
long long l3 = l1 - 1;
long long l4 = l3 + 1;
cout << l1 << "\n";
cout << l2 << "\n";
cout << l3 << "\n";
cout << l4 << "\n";

return 0;
}

Выход:

-9223372036854775808
-9223372036854775808
9223372036854775807
-9223372036854775808
0

По вопросам рекламы [email protected]