Yep. Have a look at the code coming from the OpenBSD crowd. Those folks really know how to wield C. It involves, first and foremost, writing readable and straightforward code, in an attempt to make any bugs obvious. The OpenBSD folks also insist on code review, which also helps.
And wrt tooling: C has some of the best tooling around of any language. GCC, Clang, and Visual C++ can all do some pretty decent static analysis, and then there are tools like lint and Frama-C, and tools like valgrind. Coverity also offers free static analysis for open-source projects. Make use of all the tools available to you. Testing is also important. Shoot for 100% code coverage (see SQLite3, for example, which has a massive test suite).
As you say, one of the requirements is to pay attention to warnings and fix them. In compiler parlance, "error" means "I can't compile this code" while "warning" means "I can compile it, but it's going to misbehave at runtime".
And here's something about undefined behavior: it's possible to know which behavior is undefined and to avoid it! Not every C program is riddled with undefined behavior.
Yep. Have a look at the code coming from the OpenBSD crowd. Those folks really know how to wield C. It involves, first and foremost, writing readable and straightforward code, in an attempt to make any bugs obvious. The OpenBSD folks also insist on code review, which also helps.
And wrt tooling: C has some of the best tooling around of any language. GCC, Clang, and Visual C++ can all do some pretty decent static analysis, and then there are tools like lint and Frama-C, and tools like valgrind. Coverity also offers free static analysis for open-source projects. Make use of all the tools available to you. Testing is also important. Shoot for 100% code coverage (see SQLite3, for example, which has a massive test suite).
As you say, one of the requirements is to pay attention to warnings and fix them. In compiler parlance, "error" means "I can't compile this code" while "warning" means "I can compile it, but it's going to misbehave at runtime".
And here's something about undefined behavior: it's possible to know which behavior is undefined and to avoid it! Not every C program is riddled with undefined behavior.