Why should I always enable compiler warnings?

2020-01-22 12:48发布

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?

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

20条回答
我想做一个坏孩纸
2楼-- · 2020-01-22 12:50

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 -Wextra to the compiler.

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 -Werror to the compiler.

查看更多
来,给爷笑一个
3楼-- · 2020-01-22 12:50

Some warning may mean possible semantic error in code or possible UB. E.g. ; after if(), unused variable, global variable masked by local, or comparison of signed and unsigned. Many warnings are related to static code analyzer in compiler or to breaches of ISO standard detectable at compile time, which "require diagnostics". While those occurrences may be legal in one particular case, they would be result of design issues most of time.

Some compilers, e.g. gcc, have a command line option to activate "warnings as errors" mode, it's a nice , if cruel, tool to educate novice coders.

查看更多
我命由我不由天
4楼-- · 2020-01-22 12:51

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 -Wall and -Wextra and even -Wshadow have 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.

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 c is never used:

foo.c: In function ‘foo’:

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

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

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)

Global Variable shadowing

This one bit hard and did not show up until -Wshadow was 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.

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.

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

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

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:

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:

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=]


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.

查看更多
Fickle 薄情
5楼-- · 2020-01-22 12:54

You should definitely enable compiler warnings as some compilers are bad at reporting some common programming mistakes, including the following:-

-> initialise a variable gets forgotten -> return a value from a function get missed -> the simple arguments in printf and scanf families not matching the format string a function is used without being declared beforehand, though happens in c only

So as these functions can be detected and reported, just usually not by default; so this feature must be explicitly requested via compiler options.

查看更多
smile是对你的礼貌
6楼-- · 2020-01-22 12:55

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't until you fix the sloppy parts. There is no additional information Werror provides, it just sets priorities very clearly:

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 not to use it.

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. You have 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.

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.

查看更多
Evening l夕情丶
7楼-- · 2020-01-22 12:55

Ignoring warnings means you left sloppy code that not only could cause problems in the future for someone else, but also will make important compile messages less noticed by you. The more compiler output, the less anyone will notice or bother. Cleaner the better. It also means you know what you are doing. Warnings are very unprofessional, careless, and risky.

查看更多
登录 后发表回答