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 tha
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.
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)
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
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.
COMPILER WARNINGS ARE YOUR FRIEND (not shouting, uppercase for emphasis).
I work on legacy Fortran-77 systems. The compiler tells me valuable things: argument datatype mismatches on a subroutine call, using a local variable before a value has been set into the variable, if I have a variable or subroutine argument that is not used. These are almost always errors.
Avoiding a long post: When my code compiles cleanly, 97% it works. The other guy I work with compiles with all warnings off, spends hours or days in the debugger, then asks me to help. I just compile his code with the warnings on and tell him what to fix.
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.
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.
The compiler warnings in C++ is very useful for some reasons.
1 - It permit to show you where you can have made a mistake who can impact the final result of your operations. For example if you didn't initialize a variable or if you put "=" instead of "==" ( there are just examples )
2 - It permits also to show you where your code is not conform to the standard of the c++. It's useful because if the code is conform to the actual standard it will be easy to move the code into an other plateform for example.
In general, the warnings are very useful to show you where you have mistakes in your code who can affect the result of your algorithm or prevent some error when the user will use your program.
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.