我得到了一个 legacy code ,其中有人不小心将 double
值分配给 int
变量,例如:
int a = 10;
double b = 20;
a = b;
现在摆脱
warning C4244: '=': conversion from 'double' to 'int', possible loss of data
警告,我尝试编辑上游代码并删除不必要的 double
变量,但结果太乱了!
我也可以使用转换:
a = (int) b;
但实际上并不能保证b
会在整数范围内。我想做一个辅助函数:
int safeD2I(double inputVar){
if ((inputVar < INT_MAX) && (INT_MIN < inputVar)){
return (int) inputVar;
} else {
exit(-1);
}
}
但我不确定这是否是最佳实现方式。我想知道是否有更规范的方法来处理这个问题?
我想要的:
- 在
b
变量超出整数范围的情况下,程序立即停止 - 向终端打印一条错误消息,指出发生此问题的具体线路和时间。
在此先感谢您的支持。
最佳答案
首先,代码本身没有任何错误或不安全的地方。赋值转换是 C 语言中完全合法的部分。如果这是您不知道是否安全完成的遗留代码,您需要进行分析以确定这一点。
如果您发现确实需要捕获可能的越界值(当转换为 int
时会产生未定义的行为 (!!)),那么您的代码既错误又脆弱.比较如下:
double x;
...
if (x < INT_MAX) ...
胁迫 INT_MAX
输入 double
为了比较。在实践中double
是 IEEE double 和 int
是 32 位的,这恰好是安全的,但是如果您更改了 double
就会不安全至 float
, 因为 32 位 INT_MAX
不能用单精度表示 float
.该值将被四舍五入,然后在四舍五入后进行比较。
现在,事实证明您还有一个差一错误(<= INT_MAX
,而不是< INT_MAX
,是在边界内)以及不正确的逻辑(||
而不是 &&
)所以四舍五入实际上会修复其中的一部分。但依赖它是不对的。相反,您需要制造可以比较的 2 的幂,因此转换为 float 是安全的。例如:
-
if (x < 2.0*(INT_MAX/2+1) && x >= INT_MIN)
-
if (-x > (-INT_MAX-1) && x >= INT_MIN)
-
if (-x > INT_MIN && x >= INT_MIN)
这些都假设INT_MIN
实际上是二的幂(全范围二进制补码),这是一个合理的现实世界假设,也是 C2x+ 所要求的。如果你想要更多的通用性,那就需要更多的工作。
最后,我首先写这个作为对你问题的评论,但我想得越多,它确实属于一个答案:根据你的 C 熟练程度,我会非常谨慎 对此代码进行任何不必要的或“清理”更改。你破坏的可能远远多于你修复的。仅在您已完成分析以确定存在事件错误的地方进行更改,并且不要重构事物或更改类型来修复。进行简单的直接内联修复。
关于c - 将 double 转换为 int 的安全方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60801020/