I would expect the following C code to produce 8, 16 for the first printf (it does), and 1, 0 for the second (however, it produces 0, 0). Why is that? (This is on MacOS on an Intel Core i7.)
typedef unsigned long long ll;
typedef unsigned __int128 bigint;
void main() {
ll q;
bigint s;
q = 4294967296ULL; // 2**32
s = q*q;
printf("%d, %d\n", sizeof(ll), sizeof(unsigned __int128));
printf("%lld, %lld\n", s / q, s % q);
}
Edit: After modifying the code to what is below, the results are the same (and note: in the original code, I was not trying to print any 128-bit values).
void main() {
ll q;
bigint s;
q = 4294967296ULL; // 2**32
s = q*q;
printf("%zu, %zu\n", sizeof(ll), sizeof(unsigned __int128));
printf("%llu, %llu\n", (ll)(s / q), (ll)(s % q));
}
In
s = q*q;,qis a 64-bitunsigned long long, and the multiplication is performed with 64-bit arithmetic. Sinceqhas the value 232, the mathematical product, 264, does not fit in a 64-bitunsigned long long. It wraps modulo 264, so the computed result is 0.Thus
sis assigned the value 0, and this is what is printed (aside from the problems with theprintfconversion specifiers noted in the comments).You can request 128-bit arithmetic by converting at least one of the operands to the desired type: