Арифметика C++ со Смешанными Целыми Типами, вызывающая Переполнение

StackOverflow https://stackoverflow.com//questions/20031343

Вопрос

Я провел несколько тестов в VC++2010, смешивая операнды разных размеров, которые вызывают переполнение при операции добавления:

int _tmain(int argc, _TCHAR* argv[])
{
    __int8 a=127;
    __int8 b=1;
    __int16 c=b+a;
    __int8  d=b+a;
    printf("c=%d,d=%d\n",c,d);

    return 0;
}

//result is: c=128, d=-128

Я не понимаю, почему c==128!Насколько я понимаю, в обоих дополнениях b + a по-прежнему считаются добавлением 2 подписанных 8 бит переменные.Таким образом, результатом является переполнение, т.е.-128. После этого, затем результат преобразуется в 16-битный signed int для первой операции присваивания, и c все равно должен получить 16-битное значение -128.Правильно ли я понимаю?Стандарт c++ немного сложен для чтения.В главе 4, кажется, говорится о комплексном продвижении, но я не могу найти ничего, связанного с этим конкретным примером.

Это было полезно?

Решение

Насколько я понимаю, в обоих дополнениях b +a по-прежнему считаются добавлением 2 8-битных переменных со знаком.Таким образом, результатом является переполнение, т.е.-128.

Нет, повышение по службе происходит до того, как + оценивается, а не после него.Сложение происходит, когда оба a и b являются положительными.Оба номера повышены до ints для сложения, добавляется в виде двух положительных чисел, а затем преобразуется в 16-битное короткое значение.Ни на одном этапе процесса результат не становится отрицательным из-за переполнения, следовательно, конечный результат равен 128.

Возможно, в этом есть смысл:поведение a и b соответствует значению двух чисел в математике, что делает его более интуитивным для практикующих язык.

Другие советы

Это неотъемлемое продвижение.

1 Prvalue целочисленного типа, отличного от bool, char16_t, char32_t или wchar_t, ранг преобразования целого числа которого (4.13) меньше ранга int, может быть преобразовано в prvalue типа int, если int может представлять все значения исходного типа;в противном случае исходное prvalue может быть преобразовано в prvalue типа unsigned int.[§ 4.5]

В этом заявлении

 __int16 c=b+a;

Во-первых, все char и short int значения автоматически повышаются до int.Этот процесс называется комплексное продвижение.Далее все операнды преобразуются до типа самого большого операнда, который вызывается тип продвижения по службе.[Herbert Schildt]

Тот Самый ценности переменных b и a будет повышен до int и затем к ним применяется операция.

В двухкомпонентном целочисленном представлении значение со знаком представляется путем установки старшего бита.Это позволяет машине складывать и вычитать двоичные целые числа с помощью одних и тех же инструкций, независимо от того, имеет ли целое число знак.

  a = 127 == 0x7F == 0b01111111
+ b =   1 == 0x01 == 0b00000001
-------------------------------
  c = 128 == 0x80 == 0b10000000
  d =-128 == 0x80 == 0b10000000

Переменные c и d могут иметь разные типы, но разные типы целых чисел - это просто разные интерпретации одного двоичного значения.Как вы можете видеть выше, двоичное значение прекрасно укладывается в 8 бит.Поскольку стандарт требует, чтобы члены математического выражения были расширены до размера машинного слова нулем или знаком до выполняется любая математика, и ни один из операндов не будет расширен знаком, результат всегда равен 0b10000000 независимо от того, к какому типу относятся операнды.

Таким образом, разница между результатами заключается в том, что для 16-битного целого числа знаковый бит равен 0b1000000000000000 (который a+b не имеет), а для 8-битного целого числа знаковый бит равен 0b10000000 (который a+b действительно имеет).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top