Умножение в языке C/С++: знаковое и беззнаковое
Задавашись вопросом, что же всё-таки получается в результате умножения двух 8-битных операндов в случае, когда один или оба операнда представляют собой числа со знаком (signed) и без знака (unsigned), я составил небольшую тестовую программку, которая распечатывает результат вычисления для разных типов операндов и разных типов результатов.
Вот текст этой программы (исходный код):
#include <stdio.h>
typedef unsigned char uint8_t;
typedef char int8_t;
int main(void)
{
uint8_t x1, y1;
int8_t x2, y2;
short z1, z2, z3, z4;
unsigned short z5, z6, z7, z8;
printf("unsigned char\tunsigned char\tsigned char\tsigned char\t");
printf("signed short\tsigned short\tsigned short\tsigned short\t");
printf("unsigned short\tunsigned short\tunsigned short\tunsigned short\n");
printf("x1\ty1\tx2\ty2\t");
printf("z1=x1*y1\tz2=x1*y2\tz3=x2*y1\tz4=x2*y2\t");
printf("z5=x1*y1\tz6=x1*y2\tz7=x2*y1\tz8=x2*y2\n");
for(int n = 0; n<256; ++n) {
x1 = y1 = x2 = y2 = n;
z1 = x1*y1;
z2 = x1*y2;
z3 = x2*y1;
z4 = x2*y2;
z5 = x1*y1;
z6 = x1*y2;
z7 = x2*y1;
z8 = x2*y2;
printf("%d\t%d\t%d\t%d\t", x1, y1, x2, y2);
printf("%d\t%d\t%d\t%d\t", z1, z2, z3, z4);
printf("%d\t%d\t%d\t%d\n", z5, z6, z7, z8);
}
return 0;
}
Результат вычисления можно увидеть в таблице:
для микроконтроллера AVR ATmega168 (компилятор AVR-GCC) - CSV
Чтобы получить результаты для микроконтроллера AVR ATmega168, я портировал тестовую программу в скетч для Arduino, а на хосте использовал небольшой скрипт на языке Python.
Результаты меня с одной стороны порадовали, поскольку оказались идентичными для обоих процессоров, хотя для целочисленных вычислений было бы странно ожидать, что в них будет какая-нибудь погрешность.
С другой стороны я обратил внимание на то, как тип операнда влияет на вычисление. Это видно например при умножении 255*255 - в одном случае в результате получается беззнаковое 65025 (0xFE01, -511 со знаком), в другом - 65281 (0xFF01, -255 со знаком). Разница на мой взгляд довольно существенная.
Автор: Андрей Шаройко <vanyamboe@gmail.com>