В 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.
Это действительно целочисленное переполнение и артефакт дополнение двух.
На вашей реализации, LLONG_MIN
является -9223372036854775808
который 0x8000000000000000
в шестнадцатеричном (я буду использовать это шестнадцатеричное обозначение, потому что легче увидеть, что происходит с битами).
Когда вы вычисляете -LLONG_MIN
в системе, которая использует два дополнения, под капотом вы сначала делаете поразрядно-не 0x7FFFFFFFFFFFFFFF == LLONG_MAX
) затем добавьте 1, которое переполняет целое число со знаком и возвращает 0x8000000000000000 == LLONG_MIN
,
Обратите внимание, что целочисленное переполнение со знаком является неопределенным поведением, поэтому нет гарантии, что оно будет работать согласованно в каждой реализации C ++.
Хотя другой ответ правильный, я не думаю, что он объясняет интуитивную сторону этого:
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