I try to make a long int division in C, but I can't get the correct result. I'm curious about the reason why I got the crash and how can I get the correct result.
#include <stdio.h>
#include <stdint.h>
int main() {
int64_t a = 0x8000000000000000;
int64_t b = 0xffffffffffffffff;
printf("a: %ld; b: %ld\n", a, b);
int64_t c = a/b;
printf("a/b: %ld\n", c);
return 0;
}
Here is the result:
(base) ➜ ~ gcc test.c -O2
(base) ➜ ~ ./a.out
a: -9223372036854775808; b: -1
a/b = : -9223372036854775808
(base) ➜ ~ gcc test.c
(base) ➜ ~ ./a.out
a: -9223372036854775808; b: -1
[1] 39193 floating point exception (core dumped) ./a.out
CodePudding user response:
First, try using the right format specifiers. Include inttypes.h
and use printf(PRId64 "\n", x);
to print int64_t x;
. %ld
is not portable. It might work and might not.
Then note that the answer of the division int64_t c = a/b;
would be 2^63 if the integers weren't limited in size. But in fact there is no representation for that number using 64-bit 2's complement numbers. They range from -2^63
to 2^63 - 1
. That's what's causing the exception. You've overflowed the arithmetic unit that's doing the division.
Open your textbook to study up on binary integer representation.
CodePudding user response:
As you already noticed, printing a
and b
:
int64_t a = 0x8000000000000000;
int64_t b = 0xffffffffffffffff;
printf("a:%" PRId64 ", b:%" PRId64 "\n", a, b);
Yields the following:
a:-9223372036854775808, b:-1
However, dividing 64-bit signed integer INT64_MIN
by -1
on a 64-bit machine is an undefined behaviour.
A horrible artifact of two's complement arithmetic is the 'most negative number' problem. Take this code:
int8_t a = -127; //-127 to 127 OK
int8_t b = -1;
printf("a/b: %hhd\n", a/b);
This code will work for any value of a
, except for -128
(INT8_MIN
). That's because:
1000 0000 (-128)
0111 1111 (bit flip)
1000 0000 (add one, back at -128!!)
But actually if you look at the second last step:
0111 1111 (bit flip)
If you add one to that, we have already overflowed, because the first bit is reserved as a sign bit.