【问题标题】:Should you correct compiler warnings about type conversions using explicit typecasts?您是否应该使用显式类型转换更正有关类型转换的编译器警告?
【发布时间】:2011-05-28 17:27:57
【问题描述】:

在我当前的项目中,编译器显示了数百条关于类型转换的警告。

这样的代码很多

iVar = fVar1*fVar2/fVar3;
// or even
iVar = fVar1*fVar2/fVar3+.5f;

故意将float 值分配给int

当然,我可以使用

修复这些警告
iVar = (int)(...);

但这看起来有点丑。

你宁愿忍受丑陋还是忍受警告?
还是有干净的解决方案?

【问题讨论】:

  • 如果您使用 C++,我建议为此使用 static_cast
  • 你的代码做了什么丑陋的。所以它应该看起来很丑。警告比丑陋的代码丑 100 倍。

标签: c++ c type-conversion compiler-warnings


【解决方案1】:

在浮点到整数转换的情况下,我认为编写和使用函数比类型转换更好;函数本身可能使用类型转换,但我认为调用像int_round_mid_up(x) 这样的函数比(int)(x+0.5) 更好,特别是因为该函数可以很容易地编写一次,以正确处理正数和负数,包括否则-危险的 0.499999999999999944 [当添加到 0.5 时,产生 1.0],而基于类型转换的表达式 (int)(x+0.5) 将错误地将 -2.4 舍入为 -1。恕我直言,语言没有定义浮点到整数类型转换的好方法(有些使用各种形式的舍入,有些截断,有些可能使用地板;因为没有明确的“最佳”方法来进行转换,要求程序员指定需要什么比让语言选择方法更好),因此程序员应该避免在非常狭窄的上下文之外使用它们。

关于整数类型之间的转换,关于缩小转换的警告通常是好的,应该全局启用,但通过显式类型转换在本地抑制。对于大多数类型的数字工作,从doublefloat 的转换通常不应产生警告(或更糟的是,错误),但不幸的是,并非所有语言或编译器都允许这些警告被扼杀,而与其他类型的警告无关。

应该设置为为支持它的编译器生成警告的转换类别(尽管很多人不支持)是从可能产生截断结果的窄表达式转换为能够保存结果的类型如果不截断,例如

uint64_t ul = ui1 - ui2; // With ui1 and ui2 being uint32_t
double d1 = f1 / f2; // With f1 and f2 being float

如果我想要上述表达式产生的行为,我会将它们写成:

uint64_t ul = (uint32_t)(ui1 - ui2);
double d1 = (float)(f1 / f2);

否则,看到上面没有类型转换的程序员可能倾向于将它们重写为:

uint64_t ul = (uint64_t)ui1 - ui2;
double d1 = (double)f1 / f2;

这会产生一些行为,虽然更常见,但可能与程序实际需要的相反。

【讨论】:

    【解决方案2】:

    拥有数百个不是问题的警告是危险的,总有一天会出现一个真正问题的警告并淹没在噪音中。

    保持代码没有警告。

    如果您知道自己在做什么,请添加强制转换或转换。

    【讨论】:

      【解决方案3】:

      最好为任何缩小的隐式类型转换启用警告,即转换为的类型不能保存原始类型的所有值的任何转换。这包括例如float 到 int 的转换,以及有符号 int 和无符号 int 之间的任一方向的转换。这些转换可能会导致信息溢出和/或丢失,因此应始终明确说明。

      【讨论】:

        【解决方案4】:

        在我看来,有时编译器会针对我认为没有问题的问题发出警告。在这种情况下,解决方案可能是关闭那些特定的警告。但您必须谨慎行事,并确保您没有隐藏重要的警告。

        对于隐式类型转换警告,您有时需要它们,但不是所有时间。通常,您希望忽略 int 到浮点转换,但要了解其他情况。理想情况下,编译器将允许您在该粒度级别配置警告报告。

        【讨论】:

        • 我同意以前的发帖人和回答者的观点——永远不要忽视警告。始终打开它们。
        • @AlastairG 这是一个相当愚蠢和教条的说法。如果编译器出错了怎么办?
        【解决方案5】:

        是的。

        您应该始终修复编译器警告。几个原因:

        *) 这可能是错误的原因,需要实际修复,而不仅仅是强制转换。不看你就知道了。

        *) 显示为警告的实际编码错误可能会在数百个警告产生的噪音中消失

        *) 它让其他编码人员清楚地知道,你确实是想在那里使用错误类型/符号的变量。这是故意的。

        *) 它清楚明确地表明正在更改类型和/或签名。如果您的变量名称不包含类型和符号的指示,那么这可能并不明显。

        【讨论】:

        • “需要一个实际的修复,而不仅仅是一个演员表”:实际上经常发生这种情况。使用最大警告进行编译,并将警告转化为错误。
        • 实际上,在查看这些警告时,我已经发现了很多错误。
        【解决方案6】:

        我使用“警告视为错误”进行编译。警告通常表明您编写的代码不会按照您预期的方式运行。

        在这种情况下,强制类型转换会表明您正在更改类型,这意味着精度会发生变化(如果您碰巧在处理极其时间关键的代码,则会影响性能)。编写代码以最明显的方式显示其所有显式和隐式结果始终是一个很好的策略,这样您在几个月后挖掘代码后仍然知道您的代码做了什么 - 或者如果团队成员必须使用它。

        【讨论】:

          猜你喜欢
          • 2021-11-16
          • 1970-01-01
          • 1970-01-01
          • 2023-03-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多