Khi truyền nổi sang số nguyên, tràn gây ra hành vi không xác định. Từ spec C99, phần 6.3.1.4 Bất động nổi và nguyên:
Khi một giá trị hữu hạn các loại nổi thực được chuyển đổi sang một kiểu số nguyên khác hơn _Bool
, phần phân đoạn bị loại bỏ (ví dụ, giá trị được cắt ngắn về 0). Nếu giá trị của phần tích phân không thể được biểu diễn bằng kiểu số nguyên, thì hành vi là không xác định.
Bạn phải kiểm tra phạm vi một cách thủ công, nhưng không sử dụng mã như:
// DON'T use code like this!
if (my_double > INT_MAX || my_double < INT_MIN)
printf("Overflow!");
INT_MAX
là một số nguyên không đổi mà có thể không có một đại diện dấu chấm động chính xác. Khi so sánh với một phao, nó có thể được làm tròn đến giá trị dấu phẩy động lớn hơn gần nhất hoặc cao hơn gần nhất (đây là giá trị thực hiện được xác định). Với số nguyên 64 bit, ví dụ: INT_MAX
là 2^63 - 1
, thường sẽ được làm tròn thành 2^63
, do đó, bản gốc kiểm tra sẽ trở thành my_double > INT_MAX + 1
. Điều này sẽ không phát hiện tình trạng tràn nếu my_double
bằng 2^63
.
Ví dụ với gcc 4.9.1 trên Linux, chương trình sau đây
#include <math.h>
#include <stdint.h>
#include <stdio.h>
int main() {
double d = pow(2, 63);
int64_t i = INT64_MAX;
printf("%f > %lld is %s\n", d, i, d > i ? "true" : "false");
return 0;
}
in
9223372036854775808.000000 > 9223372036854775807 is false
Thật khó để có được quyền này nếu bạn không biết các giới hạn và đại diện bên trong của các số nguyên và kiểu kép trước. Nhưng nếu bạn chuyển đổi double
-int64_t
, ví dụ, bạn có thể sử dụng các hằng số thời điểm đó là đôi chính xác (giả định bổ sung và IEEE hai của đôi) nổi:
if (!(my_double >= -9223372036854775808.0 // -2^63
&& my_double < 9223372036854775808.0) // 2^63
) {
// Handle overflow.
}
Các cấu trúc !(A && B)
cũng xử lý một cách chính xác Nans.Một phiên bản di động, an toàn, nhưng không chính xác cho slighty int
s là:
if (!(my_double > INT_MIN && my_double < INT_MAX)) {
// Handle overflow.
}
này errs về phía thận trọng và sai sẽ từ chối giá trị tương đương hoặc INT_MIN
INT_MAX
. Nhưng đối với hầu hết các ứng dụng, điều này sẽ ổn.
[Số nguyên tối thiểu 32 bit đúc (-2147483648) để nổi cho số dương (2147483648.0)] (http://stackoverflow.com/q/11536389/995714) –