I would just like a few things that you guys see as bad programing practices in pure C, so I can watch out for those.
About the only thing I can think of off the top of my head:
- Frequent use of goto
More of an editorial note... "Bad programming practices" are sometimes referred to as anti-patterns. You could start a tag for that.
Embedding extern declarations in C files, instead of using header files:
extern void foo(int a, int b);
foo(1, 2);
In the future when somebody changes the implementation of foo, to take a third argument for example, the compiler won't complain because this code matches the prototype. At runtime whatever garbage happens to be in the third argument register will be passed to foo. Hijinks ensue.
C Traps and Pitfalls by Andrew Koenig is a very good reading on this subject.
I believe it can be downloaded for free as well but I don't have a direct link.
While some might disagree, I would say write code which compiles cleanly in both a C and C++ compiler. While some bits of C that break in C++ are annoying (can't use new, delete, or a bunch of other new keywords), C++ also enforces a bunch of extra checks, in particular making sure all your function prototypes match up neatly.
Of course if you do this, make sure you don't end up drifting into C++ code by accident, Unless you don't really need to stick to C of course.
I would turn the question around as there can be no real answer to your question. This is because there are so many "bad practices". Perhaps a rephrase is in order: "How will I know good C programming practices so I can know good code from bad when I see it?"
THAT we can help answer.
The most fundamental answer is; good code is like beauty - I know it when I see it even if I can't necessarily describe all its manifest forms.
A good rule of thumb for any and all programming languages is: Can I understand what's going on without being the most expert person?
A good programmer leaves those that follow - most often themselves - with many bread-crumbs to follow, leaving notes behind that describe why and how something is being done instead of just what; this is a key hallmark of a good coder.
One case in point was a bug I found due to use of single versus two digit month. The problem was not the overall logic it was that a library call that was going to convert the two digits into an integer was interpreting the leading zero as an indication that it was receiving an octal input! No, it was just a leading zero, and octal worked fine for most months, and when it got to October, it worked properly once more!... So, rather than just fix it, I left the bread-crumb comment behind why there was extra code and why the former code didn't work...
Bad code doesn't do that, and that's one easy way to tell good C (etc) programming from bad.