10312:识别危险的强制转换
题目
分析以下转换在范围、精度和未定义行为方面的风险:
c
double x = 1e100;
int y = (int)x;1
2
2
解析
在通常的实现中,1e100 可以由 double 表示为一个非常接近但未必精确等于十进制
转换为 int 时会先丢弃小数部分;但这个值远超通常的 int 范围。只要截断后的值不能由 int 表示,转换就具有未定义行为。它不保证得到 INT_MAX、低位截断结果或某个固定负数。
若某个实现连 1e100 都不能表示为有限 double,浮点常量本身还会涉及实现的翻译期范围处理,不能假定后续得到普通有限值。
安全改写
c
#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stddef.h>
bool double_to_int(double input, int *out) {
if (out == NULL || !isfinite(input)) {
return false;
}
if (input <= (double)INT_MIN ||
input >= (double)INT_MAX) {
return false;
}
*out = (int)input;
return true;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
范围检查通过前不执行转换;失败时也不修改 *out。这是一种保守接口,会拒绝两个极端边界值,以避免依赖浮点类型能否精确表示整数端点。