C++ 为什么我应该总是启用编译器警告?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/57842756/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 16:07:26  来源:igfitidea点击:

Why should I always enable compiler warnings?

c++cwarningscompiler-warningsc++-faq

提问by n. 'pronouns' m.

I often hear that when compiling C and C++ programs I should "always enable compiler warnings". Why is this necessary? How do I do that?

我经常听到在编译 C 和 C++ 程序时我应该“始终启用编译器警告”。为什么这是必要的?我怎么做?

Sometimes I also hear that I should "treat warnings as errors". Should I? How do I do that?

有时我也听说我应该“将警告视为错误”。我是不是该?我怎么做?

回答by n. 'pronouns' m.

Why enable warnings?

为什么要启用警告?

C and C++ compilers are notoriously bad at reporting some common programmer mistakes by default, such as:

C 和 C++ 编译器在默认情况下在报告一些常见的程序员错误方面是出了名的糟糕,例如:

  • forgetting to initialise a variable
  • forgetting to returna value from a function
  • arguments in printfand scanffamilies not matching the format string
  • a function is used without being declared beforehand (C only)
  • 忘记初始化变量
  • 忘记return一个函数的值
  • printfscanf系列中的参数与格式字符串不匹配
  • 函数在没有事先声明的情况下被使用(仅限 C)

These can be detected and reported, just usually not by default; this feature must be explicitly requested via compiler options.

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

How to enable warnings?

如何启用警告?

This depends on your compiler.

这取决于您的编译器。

Microsoft C and C++ compilers understand switches like /W1, /W2, /W3, /W4and /Wall. Use at least /W3. /W4and /Wallmay emit spurious warnings for system header files, but if your project compiles cleanly with one of these options, go for it. These options are mutually exclusive.

微软的C和C ++编译器理解开关一样/W1/W2/W3/W4/Wall。至少使用/W3. /W4并且/Wall可能会为系统头文件发出虚假警告,但如果您的项目使用这些选项之一进行了干净的编译,请继续使用。这些选项是相互排斥的。

Most other compilers understand options like -Wall, -Wpedanticand -Wextra. -Wallis essential and all the rest are recommended (note that, despite its name, -Wallonly enables the most important warnings, not allof them). These options can be used separately or all together.

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

Your IDE may have a way to enable these from the user interface.

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

Why treat warnings as errors? They are just warnings!

为什么将警告视为错误?它们只是警告!

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 ifit 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.

编译器警告表示您的代码中存在潜在的严重问题。上面列出的问题几乎总是致命的;其他人可能会也可能不会,但是您希望编译失败,即使结果是误报。调查每个警告,找到根本原因并修复它。在出现误报的情况下,解决它——也就是说,使用不同的语言功能或构造,以便不再触发警告。如果这被证明非常困难,请根据具体情况禁用该特定警告。

You don't want to just leave warnings as warnings even if all of them are false alarms. It could be OK for very small projects where the total number of warnings emitted is less than 7. Anything more, and it's easy for a new warning to get lost in a flood of old familiar ones. Don't allow that. Just cause all your project to compile cleanly.

即使所有警告都是误报,您也不想只将警告作为警告。对于发出警告总数小于 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 -Werroror equivalent in your releasedbuild 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.

请注意,这适用于程序开发。如果您以源代码形式向全世界发布您的项目,那么最好不要-Werror在您发布的构建脚本中提供或等效。人们可能会尝试使用不同版本的编译器或完全不同的编译器来构建您的项目,这可能会启用不同的警告集。您可能希望他们的构建成功。保持启用警告仍然是一个好主意,以便看到警告消息的人可以向您发送错误报告或补丁。

How to treat warnings as errors?

如何将警告视为错误?

This is again done with compiler switches. /WXis for Microsoft, most others use -Werror. In either case, the compilation will fail if there are any warnings produced.

这再次通过编译器开关完成。/WX适用于 Microsoft,大多数其他人使用-Werror. 在任何一种情况下,如果产生任何警告,编译都会失败。

回答by Steve Summit

C is, famously, a rather low-level language as HLLs go. C++, though it might seem to be a considerably higher-level language than C, still shares a number of its traits. And one of those traits is that the languages were designed by programmers, for programmers -- and, specifically, programmers who knew what they were doing.

众所周知,就 HLL 而言,C 是一种相当低级的语言。尽管 C++ 似乎是一种比 C 高级得多的语言,但它仍然具有许多特点。其中一个特点是语言是由程序员设计的,是为程序员设计的——特别是那些知道自己在做什么的程序员。

[For the rest of this answer I'm going to focus on C. Most of what I'll say also applies to C++, though perhaps not as strongly. Although as Bjarne Stroustrup has famously said, "C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off."]

[对于这个答案的其余部分,我将专注于 C。我要说的大部分内容也适用于 C++,尽管可能没有那么强烈。尽管正如 Bjarne Stroustrup 所说的那样,“C 让你很容易用脚射击;C++ 让它更难,但是当你这样做时,它会把你的整条腿都炸掉。” ]

If you know what you are doing -- reallyknow what you are doing -- sometimes you may have to "break the rules". But most of the time, most of us will agree that well-intentioned rules keep us all out of trouble, and that wantonly breaking those rules all the time is a bad idea.

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

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 notto 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, they'd be annoyed by a bunch of unnecessary warnings.

但是在 C 和 C++ 中,您可以做大量令人惊讶的事情,它们是“坏主意”,但并不正式“违反规则”。有时它们有时是个坏主意(但有时可能是有道理的);有时他们几乎一直都是个坏主意。但传统一直是不对这些事情发出警告——因为,再一次,假设程序员知道他们在做什么,他们不会在没有充分理由的情况下做这些事情,他们会被一群人惹恼不必要的警告。

But of course not all programmers reallyknow what they're doing. And, in particular, every C programmer (no matter how experienced) goes through a phase of being a beginning C programmer. And even experienced C programmers can get careless and make mistakes.

但当然并不是所有的程序员都真正知道他们在做什么。而且,特别是,每个 C 程序员(无论多么有经验)都经历了成为 C 程序员初学者的阶段。即使是有经验的 C 程序员也可能会粗心大意并犯错误。

Finally, experience has shown not only that programmers do make mistakes, but that these mistakes can have real, serious consequences. If you make a mistake, and the compiler doesn't warn you about it, and somehow the program doesn't immediately crash or do something obviously wrong because of it, the mistake can lurk there, hidden, sometimes for years, until it causes a reallybig problem.

最后,经验表明,不仅程序员确实会犯错误,而且这些错误会产生真正的、严重的后果。如果你犯了一个错误,编译器没有警告你,并且程序没有立即崩溃或因此做一些明显错误的事情,错误可能潜伏在那里,隐藏,有时多年,直到它导致一个非常大的问题。

So it turns out that, most of the time, warnings are a good idea, after all. Even the experienced programmers have learned (actually, it's "especiallythe 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.

所以事实证明,在大多数情况下,警告毕竟是个好主意。即使是有经验的程序员也知道(实际上,“尤其是有经验的程序员已经学会了”),总的来说,警告往往是利大于弊。因为每一次你故意做错事并且警告是令人讨厌的,你可能至少有十次不小心做错了,警告让你免于进一步的麻烦。并且当您真的想做“错误”的事情时,可以禁用或解决大多数警告。

(A classic example of such a "mistake" is the test if(a = b). Most of the time, this is a mistake, so most compilers these days warn about it -- some even by default. But if you reallywanted to both assign bto aand test the result, you can disable the warning by typing if((a = b)).)

(这种“错误”的一个典型例子是 test if(a = b)。大多数时候,这是一个错误,所以现在大多数编译器都会警告它——有些甚至是默认的。但如果你真的想同时赋值ba和测试结果,您可以通过键入来禁用警告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 terribleprocrastinator) it's easy to put off the necessarily cleanup for basically ever -- and if you get into the habit of ignoring warnings, it gets easier and easier to miss an importantwarning message that's sitting there, unnoticed, in the midst of all the ones you're ignoring.

第二个问题是,为什么要要求编译器将警告视为错误?我会说这是因为人性,特别是说“哦,这只是一个警告,这不是那么重要,我稍后会清理它”的反应太容易了。但是如果你是一个拖延者(我不了解你,但我是一个可怕的拖延者)很容易把必要的清理工作拖到永远——如果你养成了无视警告的习惯,它越来越容易错过一个重要的警告信息,它就在那里,不被注意,在你忽略的所有警告中。

So asking the compiler to treat warnings as errors is a little trick you can play on yourself to get around this human foible.

因此,要求编译器将警告视为错误是您可以自己玩的一个小技巧,以解决这个人为的弱点。

Personally, I'm not as insistent about treating warnings as errors. (In fact, if I'm honest, I can say that I virtually never 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.

就个人而言,我并不坚持将警告视为错误。(事实上​​,老实说,我可以说我几乎从未在我的“个人”编程中启用该选项。)但是您可以确定我在工作中启用了该选项,我们的风格指南(我写)强制使用它。我会说——我怀疑大多数专业程序员会说——任何不将警告视为 C 中的错误的商店都是不负责任的行为,没有遵守普遍接受的行业最佳实践。

回答by Cort Ammon

Warnings consist of the best advice some of the most skilled C++ developers could bake into an application. They're worth keeping around.

警告包括一些最熟练的 C++ 开发人员可以融入应用程序的最佳建议。他们值得留下来。

C++, being a Turing complete language, has plenty of cases where the compiler must simply trust that you knew what you are doing. However, there are many cases where the compiler can realize that you probably did not intend to write what you wrote. A classic example is printf() codes which don't match the arguments, or std::strings passed to printf (not that that everhappens to me!). In these cases, the code you wrote is not an error. It is a valid C++ expression with a valid interpretation for the compiler to act on. But the compiler has a strong hunch that you simply overlooked something which is easy for a modern compiler to detect. These are warnings. They are things that are obvious to a compiler, using all the strict rules of C++ at its disposal, that you might have overlooked.

C++ 作为一种图灵完备的语言,在很多情况下编译器必须简单地相信你知道你在做什么。但是,在很多情况下,编译器可以意识到您可能并不打算编写您所写的内容。一个经典的例子是与参数不匹配的 printf() 代码,或者传递给 printf 的 std::strings (我从来没有遇到这种情况!)。在这些情况下,您编写的代码不是错误。它是一个有效的 C++ 表达式,具有供编译器执行的有效解释。但是编译器有一种强烈的预感,你只是忽略了一些现代编译器很容易检测到的东西。这些是警告。对于编译器来说,它们是显而易见的,使用 C++ 的所有严格规则,您可能会忽略。

Turning warnings off, or ignoring them, is like choosing to ignore free advice from those more skilled than you. Its a lesson in huberis that ends either when you fly too close to the sun and your wings melt, or a memory corruption error occurs. Between the two, I'll take falling from the sky any day!

关闭或忽略警告就像选择忽略那些比你更熟练的人的免费建议。这是一个关于huberis的教训,当你飞得太靠近太阳并且你的翅膀融化时结束,或者发生内存损坏错误。两者之间,我任天而降!

"Treat warnings as errors" is the extreme version of this philosophy. The idea here is that you resolve everywarning the compiler gives you -- you listen to every bit of free advice and act on it. Whether this is a good model for development for you depends on the team and what kind of product you are working on. It's the ascetic approach that a monk might have. For some, it works great. For others, it does not.

“将警告视为错误”是这种哲学的极端版本​​。这里的想法是你解决编译器给你的每一个警告——你听取每一个免费的建议并采取行动。这对你来说是否是一个好的开发模型取决于团队和你正在开发的产品类型。这是一个和尚可能有的苦行方法。对某些人来说,效果很好。对于其他人,它没有。

On many of my applications we do not treat warnings as errors. We do this because these particular applications need to compile on several platforms with several compilers of varying ages. Sometimes we find it is actually impossible to fix a warning on one side without it turning into a warning on another platform. So we are merely careful. We respect warnings, but we don't bend over backwards for them.

在我的许多应用程序中,我们不会将警告视为错误。我们这样做是因为这些特定的应用程序需要在多个平台上使用不同年龄的多个编译器进行编译。有时我们发现实际上不可能在一侧修复警告而不将其变成另一个平台上的警告。所以我们只是小心翼翼。我们尊重警告,但我们不会为它们而退缩。

回答by RedSonja

Not only does handling the warnings make better code, it makes you a better programmer. Warnings will tell you about things that may seem little to you today, but one day that bad habit will come back and bite your head off.

处理警告不仅可以编写更好的代码,还可以让您成为更好的程序员。警告会告诉你一些今天对你来说似乎微不足道的事情,但总有一天这种坏习惯会卷土重来,咬你一口。

Use the correct type, return that value, evaluate that return value. Take time and reflect "Is this really the correct type in this context?" "Do I need to return this?" And the biggie; "Is this code going to be portable for the next 10 years?"

使用正确的类型,返回该值,评估该返回值。花点时间思考“在这种情况下,这真的是正确的类型吗?” “这个需要我还吗?” 还有大人物;“这个代码在接下来的 10 年里是可移植的吗?”

Get into the habit of writing warning-free code in the first place.

首先养成编写无警告代码的习惯。

回答by Josiah

The other answers are excellent and I don't want to repeat what they have said.

其他答案都很好,我不想重复他们所说的。

One other aspect to "why enable warnings" that hasn't properly been touched on is that they help enormously with code maintenance. When you write a program of significant size, it becomes impossible to keep the whole thing in your head at once. You typically have a function or three that you're actively writing and thinking about, and perhaps a file or three on your screen that you can refer to, but the bulk of the program exists in the background somewhere and you have to trust that it keeps working.

“为什么启用警告”没有被正确提及的另一方面是它们对代码维护有很大帮助。当你编写一个相当大的程序时,不可能一下子把整个事情都记在脑子里。你通常有一个或三个你正在积极编写和思考的函数,也许你的屏幕上有一三个文件你可以参考,但大部分程序存在于后台的某个地方,你必须相信它继续工作。

Having warnings on, and having them as energetic and in your face as possible, helps to alert you if something you change makes trouble for something that you can't see.

发出警告,并让它们尽可能充满活力,并尽可能地出现在您的脸上,如果您更改的某些内容为您看不到的内容带来麻烦,则有助于提醒您。

Take for example, the clang warning -Wswitch-enum. That triggers a warning if you use a switch on an enum and miss out one of the possible enum values. It's something you might think would be an unlikely mistake to make: you probably at least looked at the list of enum values when you wrote the switch statement. You might even have an IDE that generated the switch options for you, leaving no room for human error.

以 clang 警告为例-Wswitch-enum。如果您在枚举上使用开关并错过了可能的枚举值之一,则会触发警告。您可能认为这是一个不太可能犯的错误:您可能至少在编写 switch 语句时查看了枚举值列表。您甚至可能有一个 IDE 为您生成开关选项,没有人为错误的余地。

This warning really comes into its own when, six months later you add another possible entry to the enum. Again, if you're thinking about the code in question you'll probably be fine. But if this enum is used for multiple different purposes and it's for one of those that you need the extra option, it's very easy to forget to update a switch in a file you haven't touched for 6 months.

六个月后,当您向枚举添加另一个可能的条目时,此警告才真正发挥作用。同样,如果您正在考虑有问题的代码,您可能会没事。但是,如果这个枚举用于多种不同的目的,并且它是您需要额外选项的目的之一,那么很容易忘记更新您已经 6 个月没有接触过的文件中的开关。

You can think of warnings in the same way as you'd think of automated test cases: they help you make sure that the code is sensible and doing what you need when you first write it, but they help even more to make sure that it keeps doing what you need while you prod at it. The difference is that test cases work very narrowly to the requirements of your code and you have to write them, while warnings work broadly to sensible standards for almost all code, and they're very generously supplied by the boffins who make the compilers.

您可以像思考自动化测试用例一样思考警告:它们帮助您确保代码合理并在您第一次编写代码时执行您需要的操作,但它们更有助于确保代码不断地做你需要做的事,而你却在努力。不同之处在于,测试用例仅适用于您的代码要求,您必须编写它们,而警告则适用于几乎所有代码的合理标准,并且它们由制作编译器的专家非常慷慨地提供。

回答by gsamaras

Non-fixed warnings will, sooner or later, lead to errors in your code.

未修复的警告迟早导致您的代码出错



Debugging a segmentation fault, for instance, requires the programmer to trace the root (cause) of the fault, which usually is located in a prior place in your code than the line that eventually caused the segmentation fault.

例如,调试分段错误需要程序员跟踪错误的根源(原因),该根源通常位于代码中比最终导致分段错误的那一行更早的位置。

It's very typical that the cause is a line for which the compiler had issued a warning that you ignored, and the line that caused the segmentation fault the line that eventually threw the error.

很典型的原因是编译器发出了您忽略的警告的行,而导致分段错误的行是最终引发错误的行。

Fixing the warning leads to fixing the problem.. A classic!

修复警告导致修复问题..经典!

A demonstration of the above.. Consider the following code:

上面的演示..考虑以下代码:

#include <stdio.h>

int main(void) {
  char* str = "Hello world!";
  int idx;

  // Colossal amount of code here, irrelevant to 'idx'

  printf("%c\n", str[idx]);

  return 0;
}

which when compiled with "Wextra" flag passed to GCC, gives:

当使用传递给 GCC 的“Wextra”标志编译时,给出:

main.c: In function 'main':
main.c:9:21: warning: 'idx' is used uninitialized in this function [-Wuninitialized]
    9 |   printf("%c\n", str[idx]);
      |                     ^

which I couldignore and execute the code anyway.. And then I would witness a "grand" segmentation fault, as my IP epicurus professor used to say:

无论如何,我可以忽略并执行代码..然后我会目睹一个“大”分段错误,正如我的 IP 史诗教授曾经说过的那样:

Segmentation fault

分段故障

In order to debug this in a real world scenario, one would start from the line that causes the segmentation fault and attempt to trace what is the root of the cause.. They would have to search for what has happened to iand strinside that colossal amount of code over there...

为了在真实的场景中调试这个,一会从引起分段错误行开始,并试图追查是什么原因的根源。他们将不得不寻找发生了什么事i,并str认为巨大的金额内那边的代码...

Until, one day, they found theirselves in the situation where they discover that idxis used uninitialized, thus it has a garbage value, which results in indexing the string (way) beyond out of its bounds, which leads to a segmentation fault.

直到有一天,他们发现自己处于idx未初始化使用的情况,因此它具有垃圾值,导致将字符串(方式)索引到超出其边界,从而导致分段错误。

If only they hadn't ignored the warning, they would have found the bug immediately!

如果他们没有忽略警告,他们会立即发现错误!

回答by Dmitry Grigoryev

Treating warnings as errors is just a mean of self-discipline: you were compiling a program to test that shiny new feature, but you can'tuntil you fix the sloppy parts. There is no additional information Werrorprovides, it just sets priorities very clearly:

将警告视为错误只是自律的一种手段:您正在编译一个程序来测试这个闪亮的新功能,但在修复草率部分之前您不能这样做。没有Werror提供额外的信息,它只是非常明确地设置了优先级:

Don't add new code until you fix problems in the existing code

在修复现有代码中的问题之前不要添加新代码

It's really the mindset that's important, not the tools. Compiler diagnostics output is a tool. MISRA (for embedded C) is another tool. It doesn't matter which one you use, but arguably compiler warnings is the easiest tool you can get (it's just one flag to set) and the signal to noise ratio is very high. So there's no reason notto use it.

真正重要的是心态,而不是工具。编译器诊断输出是一个工具。MISRA(用于嵌入式 C)是另一个工具。您使用哪一个并不重要,但可以说编译器警告是您可以获得的最简单的工具(它只是要设置的一个标志)并且信噪比非常高。所以没有理由使用它。

No tool is infallible. If you write const float pi = 3.14;, most tools won't tell you that you defined π with a bad precision which may lead to problems down the road. Most tools won't raise an eyebrow on if(tmp < 42), even if it's commonly known that giving variables meaningless names and using magic numbers is a way to disaster in big projects. Youhave to understand that any "quick test" code you write is just that: a test, and you have to get it right before you move on to other tasks, while you still see its shortcomings. If you leave that codes as is, debugging if after you spend two months adding new features will be significantly harder.

没有任何工具是万无一失的。如果你写const float pi = 3.14;,大多数工具不会告诉你你定义的 π 精度很差,这可能会导致问题。大多数工具不会引起人们的注意if(tmp < 42),即使众所周知,给变量赋予无意义的名称和使用幻数是在大型项目中造成灾难的一种方式。必须明白,您编写的任何“快速测试”代码就是这样:一个测试,您必须在继续执行其他任务之前正确地进行测试,同时您仍然会看到它的缺点。如果您将这些代码保留原样,那么在花费两个月的时间添加新功能后进行调试将变得更加困难。

Once you get into the right mindset, there is no point in using Werror. Having warnings as warnings will allow you to take an informed decision whether it still makes sense to run that debug session you were about to start, or to abort it and fix the warnings first.

一旦你进入正确的心态,使用Werror. 将警告作为警告将允许您做出明智的决定,是运行您即将启动的调试会话仍然有意义,还是中止它并首先修复警告。

回答by Dom

As someone who works with legacy embedded C code, enabling compiler warnings has helped show a lot of weakness and areas to investigate when proposing fixes. In gcc utilizing -Walland -Wextraand even -Wshadowhave become vital. I'm not going to go every single hazard, but I'll list a few that have popped up that helped show code issues.

作为使用遗留嵌入式 C 代码的人,启用编译器警告有助于在提出修复方案时显示许多弱点和需要调查的领域。在 gcc 中使用-Wall-Wextra甚至-Wshadow已经变得至关重要。我不会去处理每一个危险,但我会列出一些帮助显示代码问题的弹出窗口。

Variables being left behind

遗留变量

This one can easily point to unfinished work and areas that might not be utilizing all of the passed variables which could be an issue. Let's look at a simple function that may trigger this:

这个可以很容易地指向未完成的工作和可能没有利用所有传递变量的区域,这可能是一个问题。让我们看一个可能触发这个的简单函数:

int foo(int a, int b)
{
   int c = 0;

   if (a > 0)
   {
        return a;
   }
   return 0;
}

Just compiling this without -Wall or -Wextra returns no issues. -Wall will tell you though that cis never used:

仅在没有 -Wall 或 -Wextra 的情况下编译它不会返回任何问题。-Wall 会告诉你虽然c从未使用过:

foo.c: In function ‘foo':

foo.c:9:20: warning: unused variable ‘c' [-Wunused-variable]

foo.c:在函数“foo”中:

foo.c:9:20: 警告:未使用的变量 'c' [-Wunused-variable]

-Wextra will also tell you that your parameter b doesn't do anything:

-Wextra 还会告诉你你的参数 b 没有做任何事情:

foo.c: In function ‘foo':

foo.c:9:20: warning: unused variable ‘c' [-Wunused-variable]

foo.c:7:20: warning: unused parameter ‘b' [-Wunused-parameter] int foo(int a, int b)

foo.c:在函数“foo”中:

foo.c:9:20: 警告:未使用的变量 'c' [-Wunused-variable]

foo.c:7:20: 警告:未使用的参数 'b' [-Wunused-parameter] int foo(int a, int b)

Global Variable shadowing

全局变量阴影

This one bit hard and did not show up until -Wshadowwas used. Let's modify the example above to just add, but there just happens to be a global with the same name as a local which causes a lot of confusion when trying to use both.

这有点硬,直到-Wshadow使用才出现。让我们修改上面的例子,只是添加,但恰好有一个与本地名称相同的全局变量,这在尝试同时使用两者时会引起很多混乱。

int c = 7;

int foo(int a, int b)
{
   int c = a + b;
   return c;
}

When -Wshadow was turned on, it's easy to spot this issue.

当 -Wshadow 开启时,很容易发现这个问题。

foo.c:11:9: warning: declaration of ‘c' shadows a global declaration [-Wshadow]

foo.c:1:5: note: shadowed declaration is here

foo.c:11:9: 警告:'c' 的声明会影响全局声明 [-Wshadow]

foo.c:1:5: 注意:隐藏声明在这里

Format strings

格式化字符串

This doesn't require any extra flags in gcc, but it has still be the source of problems in the past. A simple function trying to print data, but has a formatting error could look like this:

这在 gcc 中不需要任何额外的标志,但它仍然是过去问题的根源。一个尝试打印数据但有格式错误的简单函数可能如下所示:

void foo(const char * str)
{
    printf("str = %d\n", str);
}

This doesn't print the string since the formatting flag is wrong and gcc will happily tell you this is probably not what you wanted:

这不会打印字符串,因为格式标志是错误的,gcc 会很高兴地告诉你这可能不是你想要的:

foo.c: In function ‘foo':

foo.c:10:12: warning: format ‘%d' expects argument of type ‘int', but argument 2 has type ‘const char *' [-Wformat=]

foo.c:在函数“foo”中:

foo.c:10:12: 警告:格式 '%d' 需要类型为 'int' 的参数,但参数 2 的类型为 'const char *' [-Wformat=]



These are just three of the many things the compiler can double check for you. There are a lot of others like using an uninitialized variable that others have pointed out.

这些只是编译器可以为您仔细检查的众多内容中的三个。还有很多其他人喜欢使用其他人指出的未初始化变量。

回答by Joshua

This is a specific answer to C, and why this is far more important to C than to anything else.

这是对 C 的特定答案,以及为什么这对 C 比其他任何事情都重要得多。

#include <stdio.h>
int main()
{
   FILE *fp = "some string";
}

This code compiles with a warning. What are and should be errors in just about every other language on the planet (barring assembly language) are warningsin C. Warnings in C are almost always errors in disguise. Warnings should be fixed, not suppressed.

此代码编译时发出警告。是什么,应该是在几乎地球上所有其他的语言错误(除非汇编语言)的警告,在警告C.用C几乎都是变相的错误。警告应该被修复,而不是被压制。

With gcc, we do this as gcc -Wall -Werror.

随着gcc,我们这样做gcc -Wall -Werror

This was also the reason for the high rantyness about some MS non-secure API warnings. Most people programming C have learned the hard way to treat warnings as errors and this stuff appeared that just wasn't the same kind of thing and wanted non-portable fixes.

这也是对一些 MS 非安全 API 警告的高度评价的原因。大多数编程 C 的人已经学会了将警告视为错误的艰难方法,而这些东西似乎不是同一类东西,需要非便携式修复。

回答by S.S. Anne

You should always enable compiler warnings because the compiler can often tell you what's wrong with your code. To do this, you pass -Wall -Wextrato the compiler.

您应该始终启用编译器警告,因为编译器通常会告诉您代码有什么问题。为此,您需要传递-Wall -Wextra给编译器。

You should usually treat warnings as errors because the warnings usually signify that there's something wrong with your code. However, it's often very easy to ignore these errors. Therefore, treating them as errors will cause the build to fail so you can't ignore the errors. To treat warnings as errors, pass -Werrorto the compiler.

您通常应该将警告视为错误,因为警告通常表示您的代码有问题。但是,通常很容易忽略这些错误。因此,将它们视为错误会导致构建失败,因此您不能忽略这些错误。要将警告视为错误,请传递-Werror给编译器。