Yes, there is logic.
As KerreK wrote, integers are "wrapped" in 2 N bits that make up the width of their data type.
To make it easier, consider the following:
#include <iostream>
#include <cmath>
using namespace std;
int main() {
unsigned char tot;
unsigned char ca = 200;
unsigned char ca2 = 200;
tot = ca * ca2;
cout << (int)tot;
return 0;
}
(: http://ideone.com/nWDYjO)
char 1 (. 255 ), 200 * 200 40000. unsigned char, ,
"", tot
(ca*ca2) % 256
256 - char (1 ), 2 8
(pow (10,18) * pow (10,19))% 2 number_of_bits_of_unsigned_long_long (architecture_dependent)