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

Я провел несколько тестов в 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

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

2

Решение

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

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

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

2

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

Это неотъемлемая реклама.

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

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

 __int16 c=b+a;

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

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

1

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

  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 имеет).

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