1

在我的代码中,我用 0、1 和 2 值(或其他小整数)初始化了很多浮点数。虽然 GCC 不会对此产生警告,但 MSVC 会。因此,我将所有 0 替换为0.f,将 1替换为1.f等等...同时用 0.5 初始化浮点数会发出警告,我将其替换为 0.5f。

虽然我完全理解这样做float f=someIntfloat f=someDouble应该产生警告,因为在某些情况下会丢失精度,但编译器应该足够聪明,知道 0、1、2 和 0.5 是精确的浮点值。而且我的代码的可读性要差得多……

MSVC 没有使用某些标准吗?我应该让他抱怨还是降低我的代码可读性?

谢谢!

4

2 回答 2

2

[...] 编译器应该足够聪明,知道 0、1、2 和 0.5 是精确的浮点值。

情况可能是这样,但是您真的希望编译器使用这些知识来抑制警告吗?考虑以下代码片段:

double fun()
{
    float calculated = UNIVERSAL_BASE_VALUE;
    // Do some calculations.
    return calculated;
}

假设UNIVERSAL_BASE_VALUE是在某处的头文件中定义的常量。也许它的类型是double. 但它的值可能是 0.5,这是一个精确float值,因此在这种情况下,编译器可以使用它的知识来抑制警告。

现在快进几年。这个好玩的功能暂时没碰过,但是生意变了,有人想试试把UNIVERSAL_BASE_VALUE0.5的定义改成0.51。突然有一个编译器警告该函数多年来一直很稳定。为什么是这样?没有逻辑上的变化,只是一个小的数据变化。然而,该数据更改给出了UNIVERSAL_BASE_VALUE一个无法在float. 编译器不再对转换保持沉默。经过调查,发现calculated这些年来的类型一直是错误的,导致fun()返回的结果不准确。是时候责怪编译器太聪明了?:)

请注意,如果您UNIVERSAL_BASE_VALUE用文字替换,您会遇到类似的情况0.5。它只是让结局不那么戏剧化,而总体观点仍然成立:聪明可能会让一个错误溜走。


编译器警告旨在提醒您注意潜在的错误。这不是一门精确的科学,因为很难推断出程序员的意图,尤其是在编码风格不同的情况下。没有涵盖编译器可能选择发出的所有警告的全面标准。当出现误报时,程序员可以根据他们的具体情况做出判断。我可以想到四种基本方法可供选择。

  1. 关闭警告(因为它对您的代码没有真正的帮助)。
  2. 接受编译时会生成警告(不是一个好的选择)。
  3. 更改编码样式以适应警告(耗时)。
  4. 向编译器的开发人员抱怨(错误……很好地要求更改;不要抱怨)。

不要选择选项 2。这意味着积累人类学会忽略的警告。一旦积累了足够多的“已接受”警告,就很难发现其他弹出的警告。他们迷失在人群中,因此无法达到预期的目的。

请注意,编译器倾向于支持仅针对某些文件的某些行禁止某些警告。这在可能接受的选项 1 和 2 之间做出了折衷。

在您的情况下,您需要为您的代码库评估此警告。如果它通过发现错误来提供价值,那么您应该使用所谓的“可读性较差”。(它的可读性并没有降低,但它确实需要时间来适应它。)如果警告没有提供足够的价值来保证样式更改,请关闭警告。

于 2019-08-23T07:30:57.690 回答
-1

我建议您编写代码以无警告。

如果这使它难以阅读,则表明其他地方存在问题,例如 float 和 double 的不健康混合,这很容易导致精度损失或算术不稳定的结果。

曾几何时,我有一个程序在完成时因 coredump 而崩溃。编译器给出了一些警告,因为我有一个不健康的 char* 和 char[] 组合。

当我修复这些警告时,程序突然稳定(不再有内存损坏)。

因此,打开所有警告并更改代码以免费编译警告。

编译器只是想帮助你!

于 2019-08-23T07:41:42.737 回答