The compiler generates sequences of instructions that produce the correct result for all inputs that do not cause overflow. That's all there is to worry about (because overflow in floating point to integer conversions is undefined behavior ). The compiler does not "handle" overflows, as it completely ignores them . If the base assembly instructions (a) on the platform raise an exception, fine. If they turn around, great. If they produce meaningless results, again, fine.
, , . :
int printf(const char *, ...);
volatile double v = 0;
int main()
{
int i1 = 2147483648.0;
int i2 = 2147483648.0 + v;
printf("%d %d\n", i1, i2);
}
, i1 i2. , i1 , i2 .
, double 32- unsigned int x86-64, :
x86 .
Mac OS X Intel, 64- , double-32- int : 64- cvttsd2siq, 64 - , 32- 32- , :
$ cat t.c
#include <stdio.h>
#include <stdlib.h>
int main(int c, char **v)
{
unsigned int i = 4294967296.0 + strtod(v[1], 0);
printf("%u\n", i);
}
$ gcc -m64 -S -std=c99 -O t.c && cat t.s
…
addsd LCPI1_0(%rip), %xmm0 ; this is the + from the C program
cvttsd2siq %xmm0, %rsi ; one-instruction conversion
…
, 2 32 , ( , , 64- ).
IA-32 double 64- ( double 32- unsigned int ). 32- unsigned int , , cvttsd2si 32- :
$ gcc -m32 -S -std=c99 -O t.c && cat t.s
…
addsd LCPI1_0-L1$pb(%esi), %xmm0 ; this is the + from the C program
movsd LCPI1_1-L1$pb(%esi), %xmm1 ; conversion to unsigned int starts here
movapd %xmm0, %xmm2
subsd %xmm1, %xmm2
cvttsd2si %xmm2, %eax
xorl $-2147483648, %eax
ucomisd %xmm1, %xmm0
cvttsd2si %xmm0, %edx
cmovael %eax, %edx
…
%eax %edx. . %xmm0 , 2 31 %xmm1, , . , double int, :
if (d < 231)
then (unsigned int)(int)d
else (231 + (unsigned int)(int)(d - 231))
C double unsigned int , 32- , :
$ gcc -m32 -std=c99 -O t.c && ./a.out 123456
0