[...]
One thing to remember is that in
classic C all variables had to be declared/defined before any other
executable statements in a block of code. Sometimes it was simply not
possible to know what the value would be so initialising it at the point
of definition might be considered to be a waste of time.
Having said that, it is almost always bad code to leave a variable in an
uninitialised state. It is a recipe for future problems.
In modern "declare it whenever you like" C, I'd agree:
It is almost always better to postpone defining a variable
until you've got a reasonable initialization value. However,
if one must define earlier I feel it is usually *not* a good
idea to fabricate an initializer out of thin air. The common
advice "Initialize all pointer variables to NULL" is, I think,
a particularly bad example of bad practice.
That's not to say it was always a bad practice. A quarter
century ago compilers ran on sluggish systems in cramped memory
spaces; the basic job of translating the source code took all
the resources at their disposal and there was little left over
for dataflow analysis. If you wrote
char *evenOrOdd(int x) {
char *p;
switch (x % 2) {
case 0: p = "even"; break;
case 1: p = "odd"; break;
}
return p;
}
.... few old-time compilers would warn you that `p' might be
uninitialized in the `return' statement (because `x % 2' could
be -1). In those days, writing
char *evenOrOdd(int x) {
char *p = NULL;
switch (x % 2) {
case 0: p = "even"; break;
case 1: p = "odd"; break;
}
return p;
}
.... could be justified because it would likely give a reproducible
failure, easier to track down and solve than a Heisenbug.
But that was a quarter century ago, when machines with a few
tens of megabytes ran at a few tens of megahertz. That was back
in the days when the `register' keyword sometimes made sense. Do
you still use `register', or do you rely on the compiler's more
thorough code analysis? If the latter, why try to defeat that
same analysis when it comes to possibly uninitialized variables?
Here's what I mean by the "defeat" remark: With today's
compilers the first version of evenOrOdd() will almost certainly
elicit a diagnostic, and your attention will be drawn immediately
to the faulty code. But the second will almost certainly *not*
draw a complaint, because the compiler can see that the variable
*is* initialized -- to a garbage value, but the compiler doesn't
know NULL is garbage. Instead of detecting the bug at compile
time you detect it in testing (if you're lucky) or in deployment
(if less than lucky) or on final approach to Mars. The safeguard
that long ago improved the bug from "awful" to merely "bad" now
prevents further improvement to "averted." It's a stratagem that
refuses the compiler's offer of help -- and if you're like me,
you shouldn't refuse help.
Don't just initialize variables for initialization's sake.
It's a superstition both outmoded and harmful.