First I want to mention that I have read all the responses in this thread, I
just don't have time to respond to them all. Thanks to those who have
replied. More below:
E. Robert Tisdale said:
Are you that guy?
Yes, but are you that guy?
I'm trying not to be. There are things that I like that I can give objective
reasons for liking. For instance, I don't like K&R brace style. I like for
the braces to be at the same indentation level so it's easy to see which
braces match which. Having said that, I also am not that concerned about it
since the editor I use will show which braces match.
You need to distinguish between *style* issues
and good programming practice.
I think that all programmers blur that distinction. Is it good pragramming
practice to put the braces on the same level to show where they match or is
that just a style issue? Is it good programming practice to use if
statements instead of the ternary operator, or is that style?
I also think [that] it is wrong for coding standards
to try to prevent idiots from doing stupid things.
I don't think it's wrong.
I just don't think it works.
Yet you have advocated it!?!?
<snip>
issue that I have come across is the one way out of a function
This is a bit of a "straw man" argument.
The problem is that functions which contain multiple exit points
are extremely difficult to read, understand an maintain.
No, not at all. Consider:
int func(arglist)
{
(declarations)
int retval = BADSTATUSVALUE;
void *pointer;
if(condition1)
{
pointer = malloc(SOMESIZE);
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
if(condition2)
{
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
if(condition3)
{
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
if(condition4)
{
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
while(condition5)
{
long_line_that_ should_
be_broken_up_because_it_is_so_long_and_indented;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
retval = GOODSTATUSVALUE;
}
} /* condition4 */
} /* condition3 */
} /* condition2 */
} /* condition1*/
free(pointer);
return retval;
}
I'm sure most of us have seen code similar to the above. Now consider:
int func(arglist)
{
(declarations)
void *pointer;
if(!condition1)
return BADSTATUSVALUE:
pointer = malloc(SOMESIZE);
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
if(!condition2)
{
free(pointer);
return BADSTATUSVALUE;
}
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
if(!condition3)
{
free(pointer);
return BADSTATUSVALUE;
}
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
if(!condition4)
{
free(pointer);
return BADSTATUSVALUE;
}
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
while(condition5)
{
long_code_line_that_doesn't_have_to_be_broken;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
codeline;
}
free(pointer);
return GOODSTATUSVALUE;
}
Now then, this second example is far easier to deal with. The extreme
indentation has been eliminated, the distant brace matching has been
eliminated and the retval variable has been optimized away. This results in
several less things to keep track of. With the less indentation, fewer long
lines need to be broken up.
Suppose, for example, that you need to modify the code
and malloc some temporary storage.
How do you ensure that that storage is free'd
before any of the multiple exits?
Look at the example I've given above. If you were a maintenance programmer
adding another condition that required an early exit, you'd have to be a
complete moron not to realize that the pointer has to be freed before the
early exit. The only justification I can see for the one way out in the
first example is to protect the code from morons. That's something that you
admitted doesn't work.
Maybe you can write more concise code
with one, two, three or mre return statements.
But where do you draw the line.
The line has been drawn, perhaps somewhat arbitrarily,
at a single point of return --
preferrably at the end of the function.
This simplifies cleanup, for example,
because the thread of execution is guaranteed
to run through any statements such as free
which are placed just before it.
The examples I've given have made your point moot.
As far a coding style is concerned
that should be left up to each individual programmer.
Any rules regarding the style used for code repositories
can and should be resolved with a code reformatter such as indent
http://www.gnu.org/software/indent/indent.html
Funny you (as well as others) should mention a reformatter. I've been an
advocate of this for years. A coder would check out code, do anything they
want to it as far as style is concerned and then when they check it back in,
it is reformatted to the standard. Probably nodoby will be happy with the
results, but it is consistent. Whenever I have mentioned this in the past to
anyone, I get sort of a bemused look and an admission that it might be
interesting, but nobody ever seems to want to do it.
<snip a lot of style stuff that seems to be primarily concerned with the use
of whitespace>
Write
constant == variable
instead of
variable == constant
when comparing a variable to a constant for equality
so that if you write
constant = variable
by mistake, the compiler will detect the error.
It's amazing how much response this recommendation generated. Nobody seems
to like it. What is the sole purpose of this recommendation? It is to
protect the code from morons who can't keep track of the difference between
= and ==. Here is a case where those who responded felt that the risk was
worth the convenience of having the expression written the way they prefer
it. Yet I've had many coders of the same ilk act as if some of my
suggestions were just not worth the risk of the damage that some moron might
do to the code. Here's where it becomes a matter of where you draw the line
and unfortunately it really is subjective.
Incidentally, this rule would be better written as:
rvalue == lvalue
but the coders that need this rule probably haven't figured out the
difference between an rvalue and an lvalue anyway and admittedly the
compiler may not catch the problem for all rvalues.