#include<stdio.h>
int main(void)
{
unsigned short a,e,f ; // 2 bytes data type
unsigned int temp1,temp2,temp4; // 4 bytes data type
unsigned long temp3; // 8 bytes data type
a=0xFFFF;
e=((a*a)+(a*a))/(2*a); // Line 8
//e=(((unsigned long)(a*a)+(unsigned long)(a*a)))/(unsigned int)(2*a);
temp1=a*a;
temp2=a*a;
temp3=(unsigned long)temp1+(unsigned long)temp2; // Line 14
temp4=2*a;
f=temp3/temp4;
printf("%u,%u,%lu,%u,%u,%u,%u\n",temp1,temp2,temp3,temp4,e,f,a);
return(1);
}
How do I fix the arithmetic (At Line 8 by appropriate typecasting of intermediate results) so that overflows are taken care of ? Currently it prints 65534 instead of expected 65535.
Why is the typecast necessary for Line 14 ?
You have to promote the types before performing the overflowing operation. In line 8 that would be multiplication, so
Note that promoting only one operand of such symmetrical operations as
*is enough. You can use(unsigned) a * (unsigned) aif you wish, but(unsigned) a * awill work as well.This will take care of multiplication, which will no longer overflow. However, now the addition will overflow. While 32-bit
unsignedis enough fora * a, it is not enough fora * a + a * a. For that you’ll needunsigned long(assuming it is larger). You can formally promote the first operand of+tounsigned long(again, promoting only the first operand of
+is enough, meaning that the second multiplication can be left inunsigned).The above looks a bit too convoluted, and to make it look cleaner you can use
unsigned longin the first multiplication from the very beginningor you can just use
unsigned longeverywhere to make it look even cleanerThe very same problem appears in your
temp1 = a * a;lines. They will overflow for the very same reason. You have to doto avoid overflow, i.e. promote
abefore multiplication.And that is exactly what you correctly do in line 14, i.e. promote operands of
+before addition, although promoting only one operand is perfectly sufficient