将 double 转换为 int 的安全方法是什么?

Foa*_*oad 2 c error-handling casting safety-critical

我得到了一个遗留代码,其中有人不小心doubleint变量赋值,例如:

int a = 10;
double b = 20;
a = b;
Run Code Online (Sandbox Code Playgroud)

现在摆脱

警告 C4244:“=”:从“double”到“int”的转换,可能会丢失数据

警告,我尝试在上游编辑代码并删除不必要的double变量,但结果证明太乱了!

我也可以使用铸造:

a = (int) b;
Run Code Online (Sandbox Code Playgroud)

但实际上并不能保证b会在一个整数的范围内。我想过做一个辅助功能:

a = (int) b;
Run Code Online (Sandbox Code Playgroud)

但我不确定这是否是最好的实现。我想知道是否有更规范的方法来处理这个问题?

我想要的是:

  • b变量超出整数边界的情况下,程序立即停止
  • 向终端打印一条错误消息,指出发生此问题的具体线路和时间。

提前感谢您的支持。

R..*_*R.. 5

首先,代码按原样没有任何本质上的错误或不安全。赋值转换是 C 语言的一个完全合法的部分。如果这是遗留代码,您不知道它是否安全完成,您需要进行分析以确定它。

如果您发现确实需要捕获可能的越界值(转换为 时会产生未定义的行为(!!) int),则您的代码既错误又脆弱。比较像:

double x;
...
if (x < INT_MAX) ...
Run Code Online (Sandbox Code Playgroud)

强制INT_MAX输入double进行比较。实际上,在doubleIEEE 双精度和int32 位的世界中,这碰巧是安全的,但是例如如果您更改doublefloat,则会不安全,因为 32 位INT_MAX在单精度中无法表示float。该值将被四舍五入,然后在四舍五入后进行比较。

现在,事实证明您还有一个逐一错误(<= INT_MAX,不是< INT_MAX,是界内的)以及不正确的逻辑(||而不是&&),因此舍入实际上可以解决部分问题。但依赖它是不对的。相反,您需要制造可以比较的 2 的幂,因此转换为浮点数是安全的。例如:

  • 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实际上是 2 的幂(全范围二进制补码),这是一个合理的现实世界假设,也是 C2x+ 所要求的。如果你想要更多的普遍性,那就是更多的工作。

最后,我首先写了这个作为对你的问题的评论,但我想得越多,它真的属于一个答案:根据你的 C 熟练程度,我会非常谨慎,不要做出任何不必要的或“清理” " 更改此代码。你很可能会破坏比你修复的更多。仅在您已经完成分析以确定存在活动错误的地方进行更改,并且不要重构事物或更改类型来修复。进行简单的直接内联修复。

  • 请注意,@Foad,即使对于经验丰富的程序员来说,当负责修改现有代码而不改变其行为时,一个好的做法是准备要修改的代码的自动化测试。这些应该尽可能彻底,详细涵盖正常、极端和错误情况。可以根据原始代码验证测试,然后根据测试验证修改后的代码。做好这一点既不简单也不容易,但即使在立即代码修订任务完成之后,其结果也是对代码库的有价值的补充。 (2认同)