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

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


当前回答

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

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

其他回答

你一定要启用编译器警告,因为一些编译器不擅长报告一些常见的编程错误,包括以下:

初始化变量会被遗忘 从一个被错过的函数返回一个值 printf和scanf族中的简单参数与格式字符串不匹配 函数的使用没有事先声明,尽管这只在C中发生

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

忽略警告意味着您留下了草率的代码,这不仅会在将来给其他人带来问题,而且还会使您不太注意到重要的编译消息。

编译器输出越多,就越不会有人注意到。越干净越好。这也意味着你知道自己在做什么。警告是非常不专业、粗心和危险的。

一些警告可能意味着代码中可能出现语义错误或可能出现UB。例如;if()之后,一个未使用的变量,一个被局部变量掩盖的全局变量,或者有符号和无符号的比较。许多警告与编译器中的静态代码分析器或在编译时检测到的违反ISO标准有关,这“需要诊断”。虽然在特定情况下,这些事件可能是合法的,但大多数情况下,它们是设计问题的结果。

一些编译器,例如GCC,有一个命令行选项来激活“警告为错误”模式。这是一个很好的工具,如果残酷,教育新手。

众所周知,就hll而言,C是一种相当低级的语言。虽然c++看起来是一种比C高级得多的语言,但它仍然具有C的一些特征。其中一个特点就是这些语言是由程序员设计的,为程序员设计的——特别是那些知道自己在做什么的程序员。

(对于这个答案的其余部分,我将专注于C。我要说的大部分内容也适用于c++,尽管可能没有那么强烈。尽管Bjarne Stroustrup有一句名言:“C很容易搬起石头砸自己的脚;c++让它变得更难,但当你这样做的时候,它会把你的整条腿都炸掉。”)

如果你知道你在做什么——真的知道你在做什么——有时候你可能不得不“打破规则”。但大多数时候,我们大多数人都会同意,善意的规则让我们所有人都远离麻烦,一直肆意违反这些规则是一个坏主意。

But in C and C++, there are surprisingly large numbers of things you can do that are "bad ideas", but which aren't formally "against the rules". Sometimes they're a bad idea some of the time (but might be defensible other times); sometimes they're a bad idea virtually all of the time. But the tradition has always been not to warn about these things — because, again, the assumption is that programmers know what they are doing, they wouldn't be doing these things without a good reason, and they'd be annoyed by a bunch of unnecessary warnings.

当然,并不是所有的程序员都知道自己在做什么。特别是,每个C程序员(无论多么有经验)都要经历一个开始C程序员的阶段。即使是有经验的C程序员也会粗心大意,犯错误。

最后,经验表明,程序员不仅会犯错误,而且这些错误会产生真正的、严重的后果。如果你犯了一个错误,编译器没有警告你,而且程序没有立即崩溃,或者因为它而做一些明显的错误,这个错误可能潜伏在那里,隐藏,有时长达数年,直到它造成一个真正的大问题。

So it turns out that, most of the time, warnings are a good idea, after all. Even the experienced programmers have learned that (actually, it's "especially the experienced programmers have learned that"), on balance, the warnings tend to do more good than harm. For every time you did something wrong deliberately and the warning was a nuisance, there are probably at least ten times you did something wrong by accident and the warning saved you from further trouble. And most warnings can be disabled or worked around for those few times when you really want to do the "wrong" thing.

(这类“错误”的一个经典例子是if(A = b)的测试。大多数时候,这确实是一个错误,所以现在大多数编译器都会对此发出警告——有些甚至是默认的。但是如果你真的想把b赋值给a并测试结果,你可以通过输入if((a = b))来禁用警告。

The second question is, why would you want to ask the compiler to treat warnings as errors? I'd say it's because of human nature, specifically, the all-too-easy reaction of saying "Oh, that's just a warning, that's not so important, I'll clean that up later." But if you're a procrastinator (and I don't know about you, but I'm a world-class procrastinator) it's easy to put off the necessary cleanup for basically ever — and if you get into the habit of ignoring warnings, it gets easier and easier to miss an important warning message that's sitting there, unnoticed, in the midst of all the ones you're relentlessly ignoring.

因此,要求编译器将警告视为错误是你可以对自己玩的一个小技巧,以避免这个人类的弱点,迫使自己立即修复警告,否则你的程序将无法编译。

Personally, I'm not as insistent about treating warnings as errors — in fact, if I'm honest, I can say that I don't tend to enable that option in my "personal" programming. But you can be sure I've got that option enabled at work, where our style guide (which I wrote) mandates its use. And I would say — I suspect most professional programmers would say — that any shop that doesn't treat warnings as errors in C is behaving irresponsibly, is not adhering to commonly-accepted industry best practices.

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

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