我经常听到有人说,在编译C和c++程序时,我应该“总是启用编译器警告”。为什么这是必要的?我怎么做呢?

有时我也听到我应该“把警告当作错误”。我应该吗?我怎么做呢?


当前回答

c++编译器接受明显导致未定义行为的编译代码,这是编译器的一个主要缺陷。他们不修复这个问题的原因是,这样做可能会破坏一些可用的构建。

大多数警告应该是阻止构建完成的致命错误。默认情况下只显示错误并进行构建是错误的,如果您不覆盖它们,将警告视为错误,并留下一些警告,那么您可能会导致程序崩溃并做一些随机的事情。

其他回答

将警告视为错误只有一个问题:当你使用来自其他来源的代码时(例如,微软库,开源项目),他们没有正确地完成他们的工作,编译他们的代码会产生大量的警告。

在编写代码时,我总是确保它不会产生任何警告或错误,并在编译之前进行清理,而不会产生任何无关的噪音。我不得不处理的垃圾让我感到震惊,当我不得不构建一个大项目时,看着一串警告从编译器应该只声明它处理了哪些文件的地方经过时,我感到震惊。

我也记录我的代码,因为我知道软件真正的生命周期成本主要来自维护,而不是最初的编写,但这是另一回事……

由于某些原因,c++中的编译器警告非常有用。

它可以告诉你,你可能在哪里犯了一个错误,这可能会影响你的操作的最终结果。例如,如果你没有初始化一个变量,或者如果你使用“=”而不是“==”(这只是例子) 它还允许向你展示你的代码不符合c++标准的地方。这很有用,因为如果代码符合实际标准,那么将很容易将代码移到其他平台。

一般来说,警告是非常有用的,可以告诉您代码中哪里有错误,这些错误可能会影响算法的结果,或者在用户使用您的程序时防止出现某些错误。

别着急:你不必这么做,也没有必要。-Wall和-Werror是由代码重构狂人为自己设计的:它是由编译器开发人员发明的,目的是避免在用户端编译器或编程语言更新后破坏现有的构建。特性本身并不是什么,而是关于是否破坏构建的决定。

使用与否完全取决于您的喜好。我一直在用它,因为它能帮我改正错误。

为什么要启用警告?

众所周知,C和c++编译器在默认情况下不擅长报告一些常见的程序员错误,例如:

忘记初始化变量 忘记从函数返回值 printf和scanf族中的参数与格式字符串不匹配 函数的使用没有事先声明(仅限C语言)

这些可以被检测和报告,只是通常不是默认情况;此特性必须通过编译器选项显式地请求。

如何启用警告?

这取决于你的编译器。

微软C和c++编译器理解/W1、/W2、/W3、/W4和/Wall这样的开关。至少使用/W3。/W4和/Wall可能会对系统头文件发出错误的警告,但如果您的项目使用这些选项之一进行了干净的编译,那么就使用它。这些选择是相互排斥的。

大多数其他编译器都理解-Wall、-Wpedantic和-Wextra这样的选项。-Wall是必要的,其余的都是推荐的(注意,尽管它的名字,-Wall只启用最重要的警告,而不是全部)。这些选项可以单独使用,也可以一起使用。

您的IDE可能有办法从用户界面启用这些功能。

为什么我要把警告当作错误?它们只是警告!

A compiler warning signals a potentially serious problem in your code. The problems listed above are almost always fatal; others may or may not be, but you want compilation to fail even if it turns out to be a false alarm. Investigate each warning, find the root cause, and fix it. In the case of a false alarm, work around it — that is, use a different language feature or construct so that the warning is no longer triggered. If this proves to be very hard, disable that particular warning on a case by case basis.

你不希望只是把警告作为警告,即使它们都是假警报。对于发出的警告总数小于7的非常小的项目来说,这是可行的。再多一点,新的警告就很容易淹没在大量熟悉的旧警告中。不要允许这种情况发生。只是让你所有的项目编译干净。

Note this applies to program development. If you are releasing your project to the world in the source form, then it might be a good idea not to supply -Werror or equivalent in your released build script. People might try to build your project with a different version of the compiler, or with a different compiler altogether, which may have a different set of warnings enabled. You may want their build to succeed. It is still a good idea to keep the warnings enabled, so that people who see warning messages could send you bug reports or patches.

如何将警告视为错误?

这同样是通过编译器开关完成的。/WX是微软的,大多数其他人使用-Werror。在这两种情况下,如果产生任何警告,编译都会失败。

这就够了吗?

可能不是!随着优化级别的提高,编译器开始越来越仔细地检查代码,而这种仔细检查可能会发现更多的错误。因此,不要满足于警告开关本身,总是使用它们时,编译优化启用(-O2或-O3,或/O2如果使用MSVC)。

警告是等待发生的错误。 因此,您必须启用编译器警告,并整理代码以删除任何警告。