By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,098 Members | 1,918 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,098 IT Pros & Developers. It's quick & easy.

Coding standards

P: n/a
After years of operating without any coding standards whatsoever, the
company that I recently started working for has decided that it might be a
good idea to have some. I'm involved in this initiative.

Typically I find that coding standards are written by some guy in the
company who has a way of coding that he likes and then tries to force
everybody else to write code the way he likes it, not for any rational
reason, but simply for the subjective way he likes it. I think this is
wrong.
This is particularly irksome when it comes to issues of code layout style
which has very little relevance to the execution of the code or the
readablility and maintenance of the code.

I also think it is wrong for coding standards to try to prevent idiots from
doing stupid things. No matter how stringent some standards are, somebody
stupid is going to find a way to do something stupid to the code. My point
is that instead of making the standard more restrictive on good coders, the
bad coders should be brought up to speed to be able to write good code, not
pandered to by the standard. For example there is the seemingly universal
attitude that fully bracketed
syntax is the way to go (this will stop the idiots). I strongly disagree.
There are many times that leaving out the braces where not necessary makes
for more readable code. It also reduces the maintenance of braces; the fewer
braces the easier it is to keep braces matched up. The problem is that I
think most coders are too lazy to be bothered to know exactly when they need
braces and when they don't. If you don't know, just stick them in everywhere
that it can't hurt. Lots and lots of braces means lots and lots of code to
maintain that doesn't need to be there.

I recently read a standard that prohibited use of the ternary (conditional
?) operator. I find that most C programmers just haven't bothered to learn
how to use it and don't want others to use it, because then they'll have to
figure it out. However I have also found that in most cases where it is
used, it can make the code much clearer even for those who are not
accustomed to its use.

a = (b == c) ? d : e;

Is just as understandable and more maintainable than

if (b==c) {
a = d;
}
else {
a = e;
}

In the first case it is obvious in one line that you are simply assigning a
value to a based on the condition. The use of the if statement makes for a
lot more code that is subject to error in maintenance.

Another issue that I have come across is the one way out of a function
issue. I contend that if there are conditions that warrant an earlier exit
from a function then the early exit should be taken. For eample:

int funct( int arg )
{

.....

if (condition) return ERROR;

....

return OK;

is much better than

int funct( int arg )
{
int retval = ERROR;
.....

if ( !condition) {
retval = OK;
(rest of function);
....
} /* end of if ( !condition) */

return retval;

In the first case you've been very clear as to what values are going to be
returned, you've reduced the number of braces involved and you've reduced
the indentation level of the major part of the function. The argument
against this is that there may be some clean up that needs to be done in a
function and this style may lead an idiot to exit the function with out
doing the clean up. My rebuttal is that number one, only a small minority of
functions have the requirement that the clean up be done before exiting the
function. Number two, the clean up should be a separate function anyway that
can be called from anywhere in the parent function and number three you just
can't count on the standard to protect the code from idiots anyway so why
pretend that it does?

A similar issue is this one:

if (condition) {
retval = func(arg );
}

If that condition has to be tested before each function then the condition
should be evaluated by the function instead:

retval = func( arg, condition);

....
int func( int arg, BOOLEAN condition)
{

if (!condition) return OK;

....
}
On the whole I consider less code to be more maintainable than lots of code.
Anywhere I can reduce the lines of code then that makes it easier to
maintain. For example:

if( condition)
{
retval = func( a, b);
}
else
{
retval = func( a, c);
}

if (retval != OK)
{
error_exit_func();
}

a much better way is

if ( !func(a, condition ? b : c ) error_exit_func();
Is there anybody out there who will agree with me on these issues or am I
the lone voice for this type of coding?


Nov 14 '05
Share this Question
Share on Google+
144 Replies


P: n/a
Albert van der Horst wrote:
Natt Serrasalmus wrote:
a = (b == c) ? d : e;


a = b==c ? d : e;


a = (b == c)? d: e;

Is the space before terminators like ? and : a European thing?
Nov 14 '05 #51

P: n/a
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote in message
news:cr**********@nntp1.jpl.nasa.gov...
Albert van der Horst wrote:
Natt Serrasalmus wrote:
a = (b == c) ? d : e;


a = b==c ? d : e;


a = (b == c)? d: e;

Is the space before terminators like ? and : a European thing?


Apparently not, since I do it as well and I'm not European. However, aren't
? and : parts of a ternary _operator_, not _terminators_?

Would you write "a = b+ c;" or "a = b + c;" ? I prefer the latter, and
consider ? and : to be equivalent for formatting purposes.

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Aaron Sorkin

Nov 14 '05 #52

P: n/a
Stephen Sprunk wrote:
E. Robert Tisdale wrote:
Albert van der Horst wrote:
Natt Serrasalmus wrote:

a = (b == c) ? d : e;

a = b==c ? d : e;


a = (b == c)? d: e;

Is the space before terminators like ? and : a European thing?

Apparently not, since I do it as well and I'm not European.
However, aren't ? and : parts of a ternary _operator_, not _terminators_?

Would you write "a = b+ c;" or "a = b + c;" ? I prefer the latter,
and consider ? and : to be equivalent for formatting purposes.


Personally, I try to use the same punctuation rules
that are used for ordinary (mathematical) typesetting.
Here are my recommendations:

Terminators always follow immediately after an expression

x@ for all @ in {?, :, ,, ;}

and are followed by at least one white space.
Write

x? y: z

instead of

x ? y : z

or

x?y:z

and write

void f(int, int, int); void g(double);

instead of

void f(int,int,int);void g(double);

for example.

There is no space
between some binary operators and their operands

x@y for all @ in {::, ., ->, .*, ->*, *, /, %, &, ^, |}

but there is always a space
between other binary operators and their operands

x @ y for all @ in {+, -, <<, >>;, <, <=, >, >=, ==, !=,
&&, ||, =, *=, /=, %=, +=, -=, <<=, >>=, &=, |=, ^=}

except when expressions appear as subscripts.
Write

x + y

instead of

x+y
and

x*y

instead of

x * y

for example.
But you may wish to write

A[i+1][j-1]

instead of

A[i + 1][j - 1]

for example to subscript array A.
Most unary prefix operators never have any whitespace
between themselves and their operands

@x for all @ in {::, ++, --, ~, !, -, +, &, *}

but others do

@ x for all @ in {sizeof, new, delete, delete [], throw}

No unary postfix operators

x@ for all @ in {[], (), ++, --}

ever have any whitespace between themselves and their operands.

Use the normal typesetting rules for parentheses (),
square brackets [], angle brackets <> and curly brackets {}.
No space after (, [, < or { and no space before ), ], > or }.
Write

(x)

instead of

( x )

or

(x )

or

( x)

and write

[x]

instead of

[ x ]

or

[x ]

or

[ x]

for example.
There are, of course, exceptions
where extra white space helps to make your code more readable:

double A[2][3] = {{ 1, -1, 0},
{-10, 11, -21}};
Nov 14 '05 #53

P: n/a
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote in message
news:cr**********@nntp1.jpl.nasa.gov...
Stephen Sprunk wrote:
Apparently not, since I do it as well and I'm not European.
However, aren't ? and : parts of a ternary _operator_, not
_terminators_?

Would you write "a = b+ c;" or "a = b + c;" ? I prefer the latter,
and consider ? and : to be equivalent for formatting purposes.
Personally, I try to use the same punctuation rules
that are used for ordinary (mathematical) typesetting.


Except many operators in C are not ordinary mathematical symbols or may have
non-math meanings in certain contexts.
Here are my recommendations:

Terminators always follow immediately after an expression

x@ for all @ in {?, :, ,, ;}

and are followed by at least one white space.
I agree, except I don't consider ? and : to be terminators -- they're a
ternary operator, which I treat the same as your second group of binary
operators.
There is no space
between some binary operators and their operands

x@y for all @ in {::, ., ->, .*, ->*, *, /, %, &, ^, |}
I'd move the "math" binary operators, *, /, % and the bitwise operators &,
^, | to the following group.
but there is always a space
between other binary operators and their operands

x @ y for all @ in {+, -, <<, >>;, <, <=, >, >=, ==, !=,
&&, ||, =, *=, /=, %=, +=, -=, <<=, >>=, &=, |=, ^=}

except when expressions appear as subscripts.
Or when the use of whitespace decreases readability, common when there are
multiple levels of parens.
Most unary prefix operators never have any whitespace
between themselves and their operands

@x for all @ in {::, ++, --, ~, !, -, +, &, *}
I'd thought a space wasn't legal for these, but my compiler seems to accept
one; it never occurred to me to separate unary operators from their
operands.
but others do

@ x for all @ in {sizeof, new, delete, delete [], throw}
I use the function-like variant of sizeof so I hadn't thought of that; new,
delete, delete[], and throw are not operators in C.
No unary postfix operators

x@ for all @ in {[], (), ++, --}

ever have any whitespace between themselves and their operands.

Use the normal typesetting rules for parentheses (),
square brackets [], angle brackets <> and curly brackets {}.
No space after (, [, < or { and no space before ), ], > or }.


I agree for parens and square brackets, but disagree for angle and curly
brackets. I treat < and > the same as other "math" operators, and I always
put whitespace before/after { and } unless it severely detracts from
readability.

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Aaron Sorkin

Nov 14 '05 #54

P: n/a
Up spake Stephen Sprunk:
Most unary prefix operators never have any whitespace
between themselves and their operands


I'd thought a space wasn't legal for these, but my compiler seems to accept
one; it never occurred to me to separate unary operators from their
operands.


A common parsing technique is to convert text into tokens (discarding
whitespace along the way), then search the sequence of tokens for
patterns. Compilers implemented in this way don't care about
whitespace, only separators between tokens.

An example lexical analyzer might produce the following

"!foo" ==> EXCLAM IDENTIFIER
"! foo" ==> EXCLAM IDENTIFIER
"foo bar" ==> IDENTIFIER IDENTIFIER
"foobar" ==> IDENTIFIER

(C ignores whitespace because the standards says so, but the above might
be considered a `rationale'; in, say, lex+yacc, it's easier to write
that way.)

--
-trent
<foo> ...caffine is far less deadly.
<bar> Not if you smoke it!
Nov 14 '05 #55

P: n/a
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.org> wrote:
"Natt Serrasalmus" <Ns**********@characoid.com> writes:
"infobahn" <in******@btinternet.com> wrote in message
news:cq**********@sparta.btinternet.com...

[...]
Which "we" are you talking about? It doesn't include me.

I write if(foo(bar) != 0)


I find that form really annoying and when I see it in others code. It
suggests to me that the person who wrote it doesn't understand boolean
variables and the C idiom that was established with the C standard library.
The idiom I am referring to is that functions should return a value that
answers the question "Did anything go wrong and if so what was it?". By
that
idiom then it should be obvious to any C programmer worth their pay that

if(strcmp(string1, string2))

means "Did anything go wrong (not match up) when comparing these two
strings?" (if I wanted to know how far off they were I'd save the return
value to a variable and evaluate that, but rarely does anyone ever care how
far off the comparison was, other functions may have more interesting
non-zero return codes.)


Personally, I don't think of the result of strcmp() as a boolean
value. It's effectively a tri-state value, one of <0, 0, or >0
depending on the result of the comparison. I prefer an explicit
comparison:

if (strcmp(string1, string2) != 0) ...

If the function's name implied that it tests whether the arguments
differ, I might feel differently about it.


First, by definition it is a multi-valued function and not a boolean
function. Second, if it was a boolean function, then the person who
called it "strcmp" and not "strnotequal" should be shot.
Nov 14 '05 #56

P: n/a
Stephen Sprunk wrote:
I use the function-like variant of sizeof ...


There is no function-like variant of sizeof.
Nov 14 '05 #57

P: n/a
"Stephen Sprunk" <st*****@sprunk.org> wrote:
"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote in message
news:cr**********@nntp1.jpl.nasa.gov...
Albert van der Horst wrote:
Natt Serrasalmus wrote:

>a = (b == c) ? d : e;

a = b==c ? d : e;
a = (b == c)? d: e;

Is the space before terminators like ? and : a European thing?


Apparently not, since I do it as well and I'm not European.


Whereas I don't do it, and I am.
However, aren't ? and : parts of a ternary _operator_, not _terminators_?


Yes, but their use in natural language makes a? b: c more comfortable to
me than a ? b : c.

Richard
Nov 14 '05 #58

P: n/a
Dietmar Schindler <dS***@arcor.de> wrote:
Stephen Sprunk wrote:
I use the function-like variant of sizeof ...


There is no function-like variant of sizeof.


There's a way to use sizeof that looks as if it's a function call. For
types, it's required. For expressions, it's a consequence of the fact
that (exp) is, to all intents and purposes, the same thing as exp.

Richard
Nov 14 '05 #59

P: n/a
The idiom I am referring to is that functions should return a
value that answers the question "Did anything go wrong and
if so what was it?".
Tend to give the function a name that sounds like a predicate; i.e.
isvalid(...) would obviously return true on success; you might
use isntvalid() to cope, but often a *successful* function
won't want to return zero on success -- it will have a story
to tell.
[True Style] is a common style, but its mindshare seems to
be diminishing.
I'll believe you, though it saddens me. Pursuing the analogy
with English, frequent misspellings eventually make their
way into the dictionary, but that doesn't make misspelling
right.
there is no standard for C style
I hope we're not quibbling over a definition of "standard."
The True Style was never universally agreed, of course,
but was in very widespread use among the most elite C
programmers. Good and bad code may be written in any
style of course, but I'm sure there is (was?) a strong
positive correlation between coding in True Style and
positive traits like clarity and modularity. (I'm not
saying True Style is intrinsically conducive to good
coding practice, just that those who use it tend to have
learned from or emulate the Masters.)

Anyway, True Style certainly *was* a standard at Sun Microsystems,
a large company founded by one of the greatest Names in Unix history.
I'd expected any style mandate to be annoying but quickly became
a fan of True Style. Here are my reasons:

(1) I was mostly observing this style already, a major
exception being brace placement. I was writing
}
else
{
but in True Style this is written
} else {
The second form is simply better than the first! The former
form disconnects the keyword "else" from both its antecedent
and postcedent and is distracting to read. Also it wastes
two lines on the screen compared with the latter form, and this
is a "big deal." The left-braces in Non-true code use up
considerable vertical space and therefore more scrolling is
needed to understand a function. Smaller fonts might alleviate
this problem, but that's not an option for those of us
with poor eyesight. (Rarely, I may even run statements
together on the same line, when the statements are *very* similar,
very short, and obviously coupled.)

(2) I was proud to emulate the style of so many Masters.

(3) As I examined various software I noticed the strong correlation
between True Style and good traits like clarity and modularity.
True Style became, in my mind, a badge of honor indicating
that software deserved to be taken seriously. Linus Torvalds
also codes in True Style, so I don't think this is just a
Berkeley/Bell-Labs phenomenon.

(4) Whitespace arrangement isn't all that important but
uniformity would be convenient.
Why did all you apostates insist on deviating anyway? :-)

* * * * * * * * * * * * * * * * *

Although defense counsel continues to recommend `indent'
they offered no rebuttal to this point:
When I nest expressions of (x ? y : z), I tend to use
line-breaks and spacing to make the logic easy-to-see.
Maybe that's why the `indent' fans seemed to disparage
such nesting -- in their environment the helpful spacing
will tend to be expunged!
Are we to conclude that the defendants are satisfied to use
only indent-approved spacing? Who's being dogmatic here, anyway?

* * * * * * * * * * * * * * * * *

15 months ago, in comp.programming about "bracket convention"
I mentioned a stylistic deviation I use, and one of the
defense attorneys in the present case then responded: Blech.


Let me show this code again, my way and in an "approved style."
(Some of you may not have processed images or other arrays
with multiple homogeneous dimensions, but simple nested for-loops
are a very common idiom in such applications.)

I'm curious if any newsgrouper actually believes the "approved"
coding is more readable here.

My way:
/*
* Do a 3-D convolution.
* Convolve in_sig with conv_k producing out_sig.
* (Delivered code may be slightly different, for performance.)
*/
for (x = in_sig->beg_x; x < in_sig->end_x; x++)
for (y = in_sig->beg_y; y < in_sig->end_y; y++)
for (z = in_sig->beg_z; z < in_sig->end_z; z++) {
val = 0;
for (dx = conv_k->beg_x; dx < conv_k->end_x; dx++)
for (dy = conv_k->beg_y; dy < conv_k->end_y; dy++)
for (dz = conv_k->beg_z; dz < conv_k->end_z; dz++) {
val += in_sig->dat[x+dx][y+dy][z+dz]
* conv_k->dat[dx][dy][dz];
}
out_sig->dat[x][y][z] = val;
}
"Approved" style:
for (x = in_sig->beg_x; x < in_sig->end_x; x++)
{
for (y = in_sig->beg_y; y < in_sig->end_y; y++)
{
for (z = in_sig->beg_z; z < in_sig->end_z; z++)
{
val = 0;
for (dx = conv_k->beg_x; dx < conv_k->end_x; dx++)
{
for (dy = conv_k->beg_y; dy < conv_k->end_y; dy++)
{
for (dz = conv_k->beg_z; dz < conv_k->end_z;
dz++)
{
val += in_sig->dat[x+dx][y+dy][z+dz]
* conv_k->dat[dx][dy][dz];
}
}
}
out_sig->dat[x][y][z] = val;
}
}
}
I understand that many people, including True Stylists, will
deprecate my peculiar for-nesting, especially since the lack of
braces or indentation tends to hide the nesting. FWIW, I *never*
omit the new-line before a for-body, even if it's the trivial
for-body (";"), so (in my private universe) consecutive for's as
above will *always* be nested.

* * * * * * * * * * * * * * * * *

Finally, do let's put the small matter of source code white-space
in perspective. I'll cheerfully denounce True Style if the rest of
you will denounce the insane politics which have mesmerized a
once-great nation.
Best wishes for a Truly Stylish and Happy New Year
James Dow Allen

Nov 14 '05 #60

P: n/a
I see Google now suppresses any leading
white space in the messages I post.
Sorry about that. I'll find a better way to post
before I show code samples again.

James

Nov 14 '05 #61

P: n/a
jd*********@yahoo.com writes:
[snip]
for (x = in_sig->beg_x; x < in_sig->end_x; x++)
for (y = in_sig->beg_y; y < in_sig->end_y; y++)
for (z = in_sig->beg_z; z < in_sig->end_z; z++) {
val = 0;
for (dx = conv_k->beg_x; dx < conv_k->end_x; dx++)
for (dy = conv_k->beg_y; dy < conv_k->end_y; dy++)
for (dz = conv_k->beg_z; dz < conv_k->end_z; dz++) {
val += in_sig->dat[x+dx][y+dy][z+dz]
* conv_k->dat[dx][dy][dz];
}
out_sig->dat[x][y][z] = val;
}

[snip]

Unfortunately, we can't tell what kind of indentation you're using,
since group.google.com decided leading blanks aren't significant (a
violation of their "Don't be evil" policy IMHO). I've complained to
them about this and received what appears to be a form letter in
response.

You can fool Google into keeping the indentation by preceding each
line with a non-blank character:

| blah(blah) {
| blah;
| blah;
| }

Or you can use a different news server if you have access to one.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #62

P: n/a
Richard Bos wrote:
There's a way to use sizeof that looks as if it's a function call...


A way to use sizeof looks as if it's a function call only to a person
that is unaware of the fact that sizeof is an operator and, for types,
believes that a type can be a function argument.

(I don't suggest that you, Richard, are such a person, but am writing
this to work against misconceptions.)

Dietmar
Nov 14 '05 #63

P: n/a

"infobahn" <in******@btinternet.com> wrote in message
news:cr**********@titan.btinternet.com...
Natt Serrasalmus wrote:
"infobahn" <in******@btinternet.com> wrote in message
news:cq**********@sparta.btinternet.com...
jd*********@yahoo.com wrote:

Similarly, in C we always write "if (foo(bar))" without
debating whether "if( foo (bar))" is better a priori.

Which "we" are you talking about? It doesn't include me.

I write if(foo(bar) != 0)

I find that form really annoying


I don't.
and when I see it in others code. It suggests to me that the person who
wrote it doesn't understand boolean variables and the C idiom that was
established with the C standard library.


You are wrong to infer that. I do in fact understand boolean variables.
I also understand that in almost all cases, foo() does not return a
boolean variable, but an int.


When a logical expression is evaluated in C, it is evaluated as an integer
expression and it determines if the integer is zero or non-zero. Sounds
boolean doesn't it? Two states: either zero or non-zero.

If foo() is truly boolean in nature, then I am perfectly prepared to write if(foo(bar)) rather than
if(foo(bar) != 0)
Nothing in C is truly boolean. There is no C type for boolean. There are
only integers that are evaluated in logical expressions to be either zero or
non-zero. While that sounds like boolean values, you are technically correct
in claiming that is not truly boolean, but as far as the C language is
concerned the logical alternatives are zero or non-zero. Notice also that if
you do a logical not (!) on any non-zero value you will get zero. Perform
the same operation on zero and you get a non-zero value.

But the fact that you find the form "annoying" suggests that you need to
relax a little.
The idiom I am referring to is that functions should return a value that
answers the question "Did anything go wrong and if so what was it?".
Absolutely. And a boolean variable can only answer one of those
questions, which is why so few of my functions return boolean
variables.


I should say that none of your functions return boolean variables since
there is no such thing as a boolean variable in C. Unless of course you
create one through typedef, but what are you actually doing if you do that?
You are defining an enumerated data type that can have two values which are
either zero or some non-zero value. Are you beginning to get the feeling
that C considers integers to be boolean values that are of two kinds, zero
and non-zero when expressed in a logical context?
By that
idiom then it should be obvious to any C programmer worth their pay that

if(strcmp(string1, string2))

means "Did anything go wrong (not match up) when comparing these two
strings?"
No, it should be obvious to any C programmer worth their pay that
the result of strcmp is not boolean, but relational (negative,
zero, or positive).


The C language treats the result as a boolean value in a logical context,
it's either zero or non-zero.
(if I wanted to know how far off they were I'd save the return
value to a variable and evaluate that, but rarely does anyone ever care
how far off the comparison was, other functions may have more interesting
non-zero return codes.)
We do, however, care whether the result is negative, zero, or positive.


Why? Normally, I only care if the strings are the same or not. The distance
between each other is not something I can normally do anything about.
This form also encourages the early exit from a function:

if(strcmp(string1, string2))
return;
I, however, do not encourage early exit from a function. In all too
many cases, this makes the control flow harder for a maintenance
programmer to follow. Maintenance programmers are often under a lot
of pressure to fix a problem quickly, in code they don't know very
well. Anything we can do to help them out is a bonus, and writing
your functions to have all the structure of spaghetti bolognaise is
not helping anyone.


If you think early exits from functions results in spaghetti, then you don't
know what spaghetti is. From an earlier post:

Consider the (pseudo) code examples below:

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.

Also consider how the first example reads in the sense of ordinary language:
if condition1 keep going if condition2 keep going if condition3 keep going
etc.

as opposed to:

if not condition1 stop if not condition2 stop if not condition3 stop etc.

This is more consistent with a language that refers to traffic signals as
stoplights not golights.

If you doubt me, look at K&R where you can find numerous examples of this
form and the early exit from functions.
But nobody has to maintain the code in K&R's book. Also, whilst I
greatly admire both K, R, and their book, the day I use K&R as a
style guide is the day I grow an extra arm.


I'm not recommending K&R as a style guide, in fact there are aspects of
their style I don't care for. I was, instead, intending to point out how
they use the return values of functions such as strcmp as if they were
boolean types and also how they use them to prompt early returns from
functions. This is why C works the way it does as far as logical expressions
are concerned. The intent of the designers of the language becomes clear. It
intends for logical expressions to transcend the limits of pure boolean
algebra.
This may seem awkward at first, but you get used to it.
I am fortunate enough not to have got used to early exit from functions.
I am very happy for you if you are used to it, but I have developed my
own style based on my own reasoning and logic, and I'm quite happy to
use that style.


You might want to consider if your own reasoning and logic isn't a little
too much your own.

Your style for you; my style for me.
You should also get
used to writing your own functions in the same idiom, such that they
return zero for success and non-zero (with a value that indicates the
level of failure) for failure. This will preserve the idiom throughout
the code.
Oh, I do that already, and have done for many years.

A similar form that is particularly annoying is

if(foo(bar) == TRUE) /* where true is a macro defined as some non-zero
value */


There, I must agree with you. What makes this worse is when foo() is not
a boolean function, and yet its result is still compared against a
"boolean" symbol such as TRUE or FALSE.
{
(indented code for the entire rest of the function)
}
return somestatusvariable;


Oh, I see. You're complaining against code structure.


I'm complaining against awkward code structure.

when it should be

if(!foo(bar))
return NONZEROSTATUSVALUE;
(code for the entire rest of the function now not indented so far)
I prefer:

if(foo(bar))
{
rc = baz();
}
else
{
rc = NONZEROSTATUSVALUE;
}
return rc;

Do you have a problem with the nesting depth here?


What you wrote should be written as:

return foo(bar) ? baz() : NONZEROSTATUSVALUE;

Why should anyone have to keep track of rc when it is not needed? Why should
anyone have to follow several lines of flow of control when none are needed?

In the code you provided, it is too easy for that harried maintenance
programmer to just stick in trial bits of code inside each of the brace
pairs until they stumble upon something that takes care of the problem,
nevermind that it can create another problem or obscure the purpose of the
code. In the case I provide, the maintenance programmer should have no
trouble understanding the single line of code and if they don't (they
shouldn't be coders for a living), they had better figure it out before they
attempt any modifications. Requiring maintenance programmers to actually
know what they are doing is not a bad thing.

However assuming that you could have provided a more complicated example, I
would have expected it to be similar to the form in the re-posted (pseudo)
code example 1. Having given that example, you should have no trouble seeing
how early exits from functons improve the readability of the code.

(note also that some may have different notions as to what TRUE should be
defined as: -1, 1 etc. which makes the test against TRUE not just
idiomatically awkward, but potentially dangerous.)
Yes, that's what I thought you meant before.

Even worse is

if(a == b)
{
c = TRUE;
}
else
{
c = FALSE;
}

which should be

c = a == b;


This code, whilst correct, will have the newbies (and some older hands)
reaching for their K&Rs. Better: c = (a == b);


If it gets someone reaching for their K&Rs then so much the better. They
should be up to speed on the language. Those of us who are shouldn't have to
dumb down our code for those who aren't up to speed. In fact anyone who had
to reach for their K&R to understand that piece of code falls into the
category I was complaining about before, those who don't understand the use
of boolean values in C. As far as the parentheses are concerned, I find it a
trivial issue. Either way should not be a problem for anyone. If adding the
parentheses helps you feel better, I don't have a problem with that. The one
place I do have a problem with extraneous parentheses is when they are used
for every return value as in:

return (somestatusvariable);

When I see that it makes return look like a function call, which it isn't.
Those who code that way don't seem to understand how return works. Having
said that I don't mind something like:

return ((some_expression) operator ((some_expression) operator
(some_expression)));

Where the parentheses can clarify the meaning. For a return value like that,
I'd probably also include a comment that explained the ramifications of the
expressions.


or even worse than that

if(a == b)
{
c = FALSE;
}
else
{
c = TRUE;
}

which should be

c = !(a == b);
I would prefer c = (a != b);


While I don't see any real difference, I have to wonder why you'd find the
second way better. The way I put it preserves the sense of the original
code, but again I don't see one as having any value over the other.

Some of you may be laughing at these last two examples, but don't. I've
seen it too many times that it's not funny any more.
I didn't find them particularly funny. Just silly.

<snip>

Hardly. It's a common style, but its mindshare seems to be diminishing.

I hope its mindshare is dimishing. I would have written the above as:

if (!cap_issubset(inheritable,
cap_combine(target->cap_inheritable,

current->cap_permitted)))
goto out;


Mmmm. Well, just pray you never have to maintain my code.


I probably never will, but I have had to fix code that follows your
conventions and typically the problem arose from a maintenance programmer
who followed the same conventions and couldn't be bothered to truly
understand what the code was doing. Chances are they were intimidated by the
bulk of the code. So they just stuck a few lines of code in, maybe some
initializers and by a hacking band-aid approach managed to fix the bug they
were assigned to fix. Nevermind that they made the code even worse, even
bulkier and even harder to maintain for the next person.

This way arguments to functions are lined up.
Not in my newsreader, they aren't.


In mine they were and I used spaces, not tabs.

There's no need for any braces at all,
Well, the compiler doesn't need them. The human sometimes finds them
useful, so I put them in /all/ the time.


This human finds them to clutter up the code. I've asked several coders who
adopt your method when braces are necessary and when they aren't. I've never
met one who knew. These are people who are being paid to write C code.

The purpose of the brace is to define the beginning and end of a compound
statement. When you put braces where they are not needed, I read it as the
compiler does as in "open brace: start compound statement" then you put a
single statement where a compound statement is expected. That would be
comparable to putting punctuation in English where none is expected.

(Charlie Brown writes a letter:

Dear, Grandma,
I, had a, nice day, at school, today,. We, studied punctuation, marks.
Today, we, learned about, the, comma,. )


so leave them out leaving fewer braces to worry about which ones match
which.
For a start, they should be close enough together that you can
see which ones match which other ones.


Why should I have to see it if they aren't needed?
And even if they aren't,
if you line them up
{
like this
}

you don't have to worry about which ones match which, because it's
obvious.
I really don't have to worry about it if they aren't there.
And even if it weren't obvious, decent modern editors can
whizz you from { to } and back in the blinking of an eye.
If they aren't there at all, I don't have to ask my editor which ones match.

<snip>
I know almost nothing about the `indent' utility. Can it produce
the spacing above automatically? And suppress it when shorter
names make it unnecessary? I know about `#ifndef lint'; is there
some sort of `#ifndef indent' when one wants to preserve a helpful
white-space arrangement?

The whole point of indent is that you run code through it to
convert it to your style, making it easier for you to read.
Then, if you need to check it back into CVS, you run the
code through it again, this time to convert it to the house
style. That way, you don't screw up diff with mere whitespace
changes, and everyone's happy. Bye bye holy war.

I do agree with you on that.


Hallelujah, and amen.

Nov 14 '05 #64

P: n/a

"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote in message
news:cr**********@nntp1.jpl.nasa.gov...
Natt Serrasalmus wrote:
infobahn wrote:
I write if(foo(bar) != 0)
I find that form really annoying and when I see it in others code.
It suggests to me that
the person who wrote it doesn't understand boolean variables
and the C idiom that was established with the C standard library.


Idioms are for idiots!
The idiom I am referring to is that functions should return a value that
answers the question, "Did anything go wrong and, if so, what was it?".


That's two questions.
By that idiom then it should be obvious to any C programmer worth their
pay that

if (strcmp(string1, string2))

means "Did anything go wrong (not match up) when comparing these two
strings?"


Because the result returned by strcmp is not zero


It is one of the possible return values.
and any non zero result used as a conditional
is [implicitly] converted to true.
There's no conversion. There is no "true" in C. Logical expressions are
evaluated as integers having a value of either zero or non-zero.
(if I wanted to know how far off they were, I'd save the return value to
a variable and evaluate that
but rarely does anyone ever care how far off the comparison was,
other functions may have more interesting non-zero return codes.)
Unfortunately, the rest of us must write code
that is obvious to C programmers *not* worth their pay
as well as C programmers who are worth their pay.
This means that I write explicit code
rather than relying upon implicit conversions.
I would write:

if (0 != strcmp(string1, string2))

to detect strings which don't match.


You would pander to idiots instead of firing them. We've already seen how
nobody likes this form.

It isn't my responsibility to ferret out incompetent programmers.
Then why do you dumb down your code to accomodate them?
And I don't think that it helps to make competent programmers
work any harder than necessary to understand my intent.

My advice is, "Don't write code
that relies on competent C programmers to maintain it."
Spell it out if it is possible that
some programmer might misinterpret your intent.

Nov 14 '05 #65

P: n/a

"Alan Balmer" <al******@att.net> wrote in message
news:f0********************************@4ax.com...
On 29 Dec 2004 21:58:30 EST, "Natt Serrasalmus"
<Ns**********@characoid.com> wrote:
the C idiom that was established with the C standard library.
The idiom I am referring to is that functions should return a value that
answers the question "Did anything go wrong and if so what was it?"
But that's just not true, except for the I/O functions. Most others
return some value as a result, not as a diagnostic.

I will write "if (a)" providing 'a' is a boolean.


As I pointed out in other posts, there is no boolean in C. Logical
expressions are evaluated as integers having a value of zero or non-zero.

If not, I will write if (a != 0). If that bothers you, so be it.
If a is an integer, then it can have a value of zero or non-zero and
therefore can be treated as if it were a boolean value. Therefore, why go to
the trouble of doing the comparison?

--
Al Balmer
Balmer Consulting
re************************@att.net

Nov 14 '05 #66

P: n/a

"Keith Thompson" <ks***@mib.org> wrote in message
news:ln************@nuthaus.mib.org...
"Natt Serrasalmus" <Ns**********@characoid.com> writes:
"infobahn" <in******@btinternet.com> wrote in message
news:cq**********@sparta.btinternet.com... [...]
Which "we" are you talking about? It doesn't include me.

I write if(foo(bar) != 0)


I find that form really annoying and when I see it in others code. It
suggests to me that the person who wrote it doesn't understand boolean
variables and the C idiom that was established with the C standard
library.
The idiom I am referring to is that functions should return a value that
answers the question "Did anything go wrong and if so what was it?". By
that
idiom then it should be obvious to any C programmer worth their pay that

if(strcmp(string1, string2))

means "Did anything go wrong (not match up) when comparing these two
strings?" (if I wanted to know how far off they were I'd save the return
value to a variable and evaluate that, but rarely does anyone ever care
how
far off the comparison was, other functions may have more interesting
non-zero return codes.)


Personally, I don't think of the result of strcmp() as a boolean
value. It's effectively a tri-state value, one of <0, 0, or >0
depending on the result of the comparison.


As I pointed out elsewhere, there are no boolean values in C. C evaluates
logical expressions as integers having two possible values: zero and
non-zero. So any function that returns an integer value can be used as if it
were a boolean expression, where the boolean values are zero and non-zero.

I prefer an explicit comparison:

if (strcmp(string1, string2) != 0) ...

If the function's name implied that it tests whether the arguments
differ, I might feel differently about it.
What do you think strcmp stands for? I usually think of it as "string
compare", meaning "do the strings compare?". By that sense, the function's
name implies that it tests whether the arguments differ.

YMMV, of course, and any C programmer needs to be able to understand
the use of strcmp() in a condition (though I confess it takes me a
moment of thought).

[...]
if(foo(bar) == TRUE) /* where true is a macro defined as some non-zero
value */
{
(indented code for the entire rest of the function)
}
return somestatusvariable;

when it should be

if(!foo(bar))
return NONZEROSTATUSVALUE;
(code for the entire rest of the function now not indented so far)
On this I agree wholeheartedly. Never compare a value to TRUE or
FALSE; if such a comparison makes sense, the value is already a
condition and should be used as one.
(note also that some may have different notions as to what TRUE should be
defined as: -1, 1 etc. which makes the test against TRUE not just
idiomatically awkward, but potentially dangerous.)


Yup.

[...]
if(a == b)
{
c = FALSE;
}
else
{
c = TRUE;
}

which should be

c = !(a == b);


Or

c = (a != b);

(Yes, I like the parentheses, even though they're not strictly
necessary.)

[...]
I hope its mindshare is dimishing. I would have written the above as:

if (!cap_issubset(inheritable,
cap_combine(target->cap_inheritable,

current->cap_permitted)))
goto out;


That's indented much too deeply for my taste. Are you using hard tabs
with a non-standard tabstop setting?

I might write:

if (!cap_issubset(inheritable,
cap_combine(target->cap_inheritable,
current->cap_permitted)))


It looked like this when I posted it. I used spaces, not tabs.

...
This way arguments to functions are lined up.

[snip]

--
Keith Thompson (The_Other_Keith) ks***@mib.org
<http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*>
<http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Nov 14 '05 #67

P: n/a

"Christian Bau" <ch***********@cbau.freeserve.co.uk> wrote in message
news:ch*********************************@slb-newsm1.svr.pol.co.uk...
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.org> wrote:
"Natt Serrasalmus" <Ns**********@characoid.com> writes:
> "infobahn" <in******@btinternet.com> wrote in message
> news:cq**********@sparta.btinternet.com... [...]
>> Which "we" are you talking about? It doesn't include me.
>>
>> I write if(foo(bar) != 0)
>
> I find that form really annoying and when I see it in others code. It
> suggests to me that the person who wrote it doesn't understand boolean
> variables and the C idiom that was established with the C standard
> library.
> The idiom I am referring to is that functions should return a value
> that
> answers the question "Did anything go wrong and if so what was it?". By
> that
> idiom then it should be obvious to any C programmer worth their pay
> that
>
> if(strcmp(string1, string2))
>
> means "Did anything go wrong (not match up) when comparing these two
> strings?" (if I wanted to know how far off they were I'd save the
> return
> value to a variable and evaluate that, but rarely does anyone ever care
> how
> far off the comparison was, other functions may have more interesting
> non-zero return codes.)


Personally, I don't think of the result of strcmp() as a boolean
value. It's effectively a tri-state value, one of <0, 0, or >0
depending on the result of the comparison. I prefer an explicit
comparison:

if (strcmp(string1, string2) != 0) ...

If the function's name implied that it tests whether the arguments
differ, I might feel differently about it.


First, by definition it is a multi-valued function and not a boolean
function.


There's no such thing as a boolean function in C. See my other posts in this
thread.

Second, if it was a boolean function, then the person who called it "strcmp" and not "strnotequal" should be shot.


This is a failure to understand the C idiom that I was reffering to earlier
in the thread.
Nov 14 '05 #68

P: n/a
In article <cr********@dispatch.concentric.net>,
"Natt Serrasalmus" <Ns**********@characoid.com> wrote:
"Alan Balmer" <al******@att.net> wrote in message
news:f0********************************@4ax.com...
On 29 Dec 2004 21:58:30 EST, "Natt Serrasalmus"
<Ns**********@characoid.com> wrote:
the C idiom that was established with the C standard library.
The idiom I am referring to is that functions should return a value that
answers the question "Did anything go wrong and if so what was it?"


But that's just not true, except for the I/O functions. Most others
return some value as a result, not as a diagnostic.

I will write "if (a)" providing 'a' is a boolean.


As I pointed out in other posts, there is no boolean in C. Logical
expressions are evaluated as integers having a value of zero or non-zero.


This is anal. "Boolean" is an abstract concept, which is easily
implemented in C. Try to learn about abstraction.
Nov 14 '05 #69

P: n/a
"Natt Serrasalmus" <Ns**********@characoid.com> writes:
As I pointed out elsewhere, there are no boolean values in C.


C99 has _Bool, which has only two values: 0 and 1. This is about
as boolean as it gets.
--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Nov 14 '05 #70

P: n/a
Natt Serrasalmus wrote:
"infobahn" <in******@btinternet.com> wrote in message
news:cr**********@titan.btinternet.com...
Natt Serrasalmus wrote:
"infobahn" <in******@btinternet.com> wrote in message
news:cq**********@sparta.btinternet.com...
jd*********@yahoo.com wrote: [snip]I write if(foo(bar) != 0)
I find that form really annoying
I don't.


I write
if (foo (bar) != 0)
Nothing in C is truly boolean. There is no C type for boolean. There are
only integers that are evaluated in logical expressions to be either zero or
non-zero. While that sounds like boolean values, you are technically correct
in claiming that is not truly boolean, but as far as the C language is
concerned the logical alternatives are zero or non-zero. Notice also that if
you do a logical not (!) on any non-zero value you will get zero. Perform
the same operation on zero and you get a non-zero value.
If is usually intendent to provide an early exit from the function on
error. Really I dont think that
if (!p)
or
if (p == 0)
makes any sence, if we show that this /if/ compares p with an invalid
value, and we'll exit. But when we use strcmp all three values are valid
and we must choose one. In this case we usually continue our task, there
is no boolean statement "this value is invalid for our task" wich we
express with the if statement.
[snip]
int func(arglist)
{
(declarations)
void *pointer;

if(!condition1)
return BADSTATUSVALUE:

pointer = malloc(SOMESIZE);
codeline;
codeline; [snip] codeline;
codeline;
if(!condition2)
{
free(pointer);
return BADSTATUSVALUE;
}

codeline;
codeline; [snip] codeline;
if(!condition3)
{
free(pointer);
return BADSTATUSVALUE;
}
codeline;
codeline; [snip] codeline;
if(!condition4)
{
free(pointer);
return BADSTATUSVALUE;
}
codeline;
codeline; [snip] codeline;
while(condition5)
{
long_code_line_that_doesn't_have_to_be_broken;
codeline;
codeline; [snip] 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.

Also consider how the first example reads in the sense of ordinary language:
if condition1 keep going if condition2 keep going if condition3 keep going
etc.

as opposed to:

if not condition1 stop if not condition2 stop if not condition3 stop etc.

This is more consistent with a language that refers to traffic signals as
stoplights not golights.


Agread. by I prefer:

int foo (/* ... */)
{
FILE *f1p = NULL, *f2p = NULL;
char *s = NULL;
int res = -1;

/*
...
codelines
...
*/
f1p = fopen (fn, fmode);
if (!f1p)
goto fail;
/*
...
codelines
...
*/
f2p = fopen (fn, fmode);
if (!f2p)
goto fail;
/*
...
codelines
...
*/
s = malloc (len);
if (!s)
goto fail;
/*
...
codelines
...
*/
res = 0
fail:
free (s);
if (!f2p)
fclose (f2p);
if (!f1p)
fclose (f1p);
return res;
}

to simplify the cleanup.
Nov 14 '05 #71

P: n/a
Natt Serrasalmus wrote:

"infobahn" <in******@btinternet.com> wrote in message
news:cr**********@titan.btinternet.com...
Natt Serrasalmus wrote:
and when I see it in others code. It suggests to me that the person who
wrote it doesn't understand boolean variables and the C idiom that was
established with the C standard library.
You are wrong to infer that. I do in fact understand boolean variables.
I also understand that in almost all cases, foo() does not return a
boolean variable, but an int.


When a logical expression is evaluated in C, it is evaluated as an integer
expression and it determines if the integer is zero or non-zero. Sounds
boolean doesn't it? Two states: either zero or non-zero.


You missed my point. Consider the following function names:

int IsPrinterReady(PRINTER *);
int IsLeapYear(int);
int Sum(int *, size_t);
int HasTransferCompleted(DATA *);
int OpenDatabase(DB *);

All these functions return int. It is quite obvious, however, to
the experienced, intelligent, or just plain common-sense eye that
three of the five are designed to answer a Boolean question. That
is, they return a number representing 'true' or a number representing
'false'. The others do not.
If foo() is truly boolean in nature,
then I am perfectly prepared to write if(foo(bar)) rather than
if(foo(bar) != 0)
Nothing in C is truly boolean. There is no C type for boolean.


Perhaps you should read up on C's _Bool type, introduced 5 years ago.
There are
only integers that are evaluated in logical expressions to be either zero or
non-zero. While that sounds like boolean values, you are technically correct
in claiming that is not truly boolean, but as far as the C language is
concerned the logical alternatives are zero or non-zero. Notice also that if
you do a logical not (!) on any non-zero value you will get zero. Perform
the same operation on zero and you get a non-zero value.
I suspect this is a paradigm thing. We just don't see data the same
way. So we're unlikely ever to agree on this.
The idiom I am referring to is that functions should return a value that
answers the question "Did anything go wrong and if so what was it?".


Absolutely. And a boolean variable can only answer one of those
questions, which is why so few of my functions return boolean
variables.


I should say that none of your functions return boolean variables since
there is no such thing as a boolean variable in C.


Wrong in fact and wrong in spirit. Even before C introduced _Bool,
it was possible to use ints (and other integer types) as Boolean
values, by the simple method of only ever writing a 0 or a 1 to
them.
By that
idiom then it should be obvious to any C programmer worth their pay that

if(strcmp(string1, string2))

means "Did anything go wrong (not match up) when comparing these two
strings?"


No, it should be obvious to any C programmer worth their pay that
the result of strcmp is not boolean, but relational (negative,
zero, or positive).


The C language treats the result as a boolean value in a logical context,
it's either zero or non-zero.


If you think strcmp is a boolean function, you are missing out on a
significant part of its functionality.
(if I wanted to know how far off they were I'd save the return
value to a variable and evaluate that, but rarely does anyone ever care
how far off the comparison was, other functions may have more interesting
non-zero return codes.)


We do, however, care whether the result is negative, zero, or positive.


Why? Normally, I only care if the strings are the same or not. The distance
between each other is not something I can normally do anything about.


Some of us need to sort strings occasionally. If you don't, fine.

This form also encourages the early exit from a function:

if(strcmp(string1, string2))
return;


I, however, do not encourage early exit from a function. In all too
many cases, this makes the control flow harder for a maintenance
programmer to follow. Maintenance programmers are often under a lot
of pressure to fix a problem quickly, in code they don't know very
well. Anything we can do to help them out is a bonus, and writing
your functions to have all the structure of spaghetti bolognaise is
not helping anyone.


If you think early exits from functions results in spaghetti, then you don't
know what spaghetti is.


Oh, but I must beg to differ. I used to generate tons of the stuff
in the days when I wrote BASIC programs.
From an earlier post:

Consider the (pseudo) code examples below:
Bleargh. All snipped, and replaced with:
int func(arglist)
{
(declarations)
int retval = BADSTATUSVALUE;

if(condition1)
{ retval = otherfunc(whatever);
} return retval;
}
Now then, this second example is far easier to deal with.
No, it's not. It's stupidly long and has far too much going on.

Learn to modularise.

<snip>

I prefer:

if(foo(bar))
{
rc = baz();
}
else
{
rc = NONZEROSTATUSVALUE;
}
return rc;

Do you have a problem with the nesting depth here?


What you wrote should be written as:

return foo(bar) ? baz() : NONZEROSTATUSVALUE;


s/should/could/

I prefer my form.
Why should anyone have to keep track of rc when it is not needed? Why should
anyone have to follow several lines of flow of control when none are needed?
You could eliminate the function call completely. You could stick
everything in main(). I am not convinced that this would lead to
more readable code.
In the code you provided, it is too easy for that harried maintenance
programmer to just stick in trial bits of code inside each of the brace
pairs until they stumble upon something that takes care of the problem,
nevermind that it can create another problem or obscure the purpose of the
code. In the case I provide, the maintenance programmer should have no
trouble understanding the single line of code and if they don't (they
shouldn't be coders for a living), they had better figure it out before they
attempt any modifications. Requiring maintenance programmers to actually
know what they are doing is not a bad thing.
In the code you provided, there's little to stop that same harried
maintenance programmer from sticking trial bits of code alongside the
conditional operator's operands, a la:

return foo(bar) ? stuff, baz() : otherstuff, NONZEROSTATUSVALUE;

Your format hardly protects against this - and nor can it. Nor,
indeed, should it be expected to. And neither should mine.
However assuming that you could have provided a more complicated example, I
would have expected it to be similar to the form in the re-posted (pseudo)
code example 1. Having given that example, you should have no trouble seeing
how early exits from functons improve the readability of the code.
You have certainly demonstrated how early exits from functions appear
to encourage long, poorly written, rambling functions.

c = a == b;


This code, whilst correct, will have the newbies (and some older hands)
reaching for their K&Rs. Better: c = (a == b);


If it gets someone reaching for their K&Rs then so much the better.


Touche'.
They should be up to speed on the language.
I agree, but nobody should have to remember precedence tables.

return (somestatusvariable);

When I see that it makes return look like a function call, which it isn't.
Well, I don't like that either, as it happens.
[...] I have had to fix code that follows your
conventions and typically the problem arose from a maintenance programmer
who followed the same conventions and couldn't be bothered to truly
understand what the code was doing. Chances are they were intimidated by the
bulk of the code. So they just stuck a few lines of code in, maybe some
initializers and by a hacking band-aid approach managed to fix the bug they
were assigned to fix. Nevermind that they made the code even worse, even
bulkier and even harder to maintain for the next person.
This has little to do with code conventions and a lot to do with
the quality of maintenance programmers.
This way arguments to functions are lined up.


Not in my newsreader, they aren't.


In mine they were and I used spaces, not tabs.


Perhaps you were using a proportional font (shrug).

There's no need for any braces at all,


Well, the compiler doesn't need them. The human sometimes finds them
useful, so I put them in /all/ the time.


This human finds them to clutter up the code. I've asked several coders who
adopt your method when braces are necessary and when they aren't. I've never
met one who knew. These are people who are being paid to write C code.


Scary! But it's another reason always to put them in.
The purpose of the brace is to define the beginning and end of a compound
statement. When you put braces where they are not needed, I read it as the
compiler does as in "open brace: start compound statement" then you put a
single statement where a compound statement is expected. That would be
comparable to putting punctuation in English where none is expected.
The C language definition does not, as far as I can tell, ascribe
a purpose to the brace character; the only hint we get is in the
grammar, which explicitly lays down that a compound statement is
composed of an *optional* declaration-list and an *optional*
statement-list (so the compound statement can legally be empty).
Furthermore, a statement-list comprises either a statement or a
statement-list followed by a statement. So the grammar specifically
caters for a compound statement containing only one statement.
(Charlie Brown writes a letter:

Dear, Grandma,
I, had a, nice day, at school, today,. We, studied punctuation, marks.
Today, we, learned about, the, comma,. )


C is not English, and the analogy is a poor one.
Nov 14 '05 #72

P: n/a
"Natt Serrasalmus" <Ns**********@characoid.com> writes:
"Alan Balmer" <al******@att.net> wrote in message
news:f0********************************@4ax.com...
On 29 Dec 2004 21:58:30 EST, "Natt Serrasalmus"
<Ns**********@characoid.com> wrote:
the C idiom that was established with the C standard library.
The idiom I am referring to is that functions should return a value that
answers the question "Did anything go wrong and if so what was it?"
But that's just not true, except for the I/O functions. Most others
return some value as a result, not as a diagnostic.

I will write "if (a)" providing 'a' is a boolean.


As I pointed out in other posts, there is no boolean in C. Logical
expressions are evaluated as integers having a value of zero or non-zero.


C99 does have a type "bool", and literals "false" and "true".
(Actually, it has a type _Bool; "bool" is a typedef, and "false" and
"true" are macros, defined in <stdbool.h>.) But C99 retains the C90
rules about zero vs. non-zero for conditions.
If not, I will write
if (a != 0). If that bothers you, so be it.


If a is an integer, then it can have a value of zero or non-zero and
therefore can be treated as if it were a boolean value. Therefore, why go to
the trouble of doing the comparison?


Since C90 doesn't make an explicit distinction between a variable that
can hold any of 2**N distinct integer values (an int) and a variable
that can hold a logically false (zero) or true (non-zero) value (an
int), we as programmers can choose to make that distinction ourselves.

If a variable "a" can meaningfully hold more than two distinct values
(e.g., a count of something), I prefer to write "if (a != 0)" rather
than "if (a)". If I'm using it to hold a true/false condition --
i.e., if I care whether it's zero or non-zero, but I never care which
non-zero value it happens to have -- then I'll write "if (a)". I'll
also give it a better name than "a", one that tells the reader at a
glance that it's a condition, perhaps something like "done" or
"valid".

A good example of this is the is*() functions in <ctype.h>. For
example, isdigit(c) returns a non-zero value if and only if its
argument is a digit. The standard says nothing about which non-zero
value it returns; it might be 1, or it might be 12345. Thus it's
logically a Boolean, and I'll use "if (isdigit(c))".

On the other hand, strcmp() returns a negative, zero, or positive
value depending on the relationship between its arguments. Even if I
don't happen to care at the moment whether it's negative or positive,
I still prefer to write "if (strcmp(a, b) == 0)" rather than
"if (!strcmp(a, b))", because the result of strcmp() isn't logically a
Boolean. (If C had the three-way if statement of ancient Fortran,
strcmp() would be a good opportunity to use it, but thankfully it
doesn't.)

Similarly, I prefer to compare the result of fopen() explicitly to
NULL rather than using it directly as a condition.

Your mileage may vary, of course, and if I see code that uses
if (!strcmp(a, b))
or
if (fp=fopen("foo.txt", "R"))
it won't give me too much trouble.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #73

P: n/a
infobahn <in******@btinternet.com> writes:
[...]
Even before C introduced _Bool, it was possible to use ints (and
other integer types) as Boolean values, by the simple method of only
ever writing a 0 or a 1 to them.


Actually, you can implement Boolean values with ints by writing zero
or non-zero to them, and by referring to them only in ways that work
the same way for any non-zero value. Treating 2 or -1 as "true" is
perfectly valid.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #74

P: n/a
"Natt Serrasalmus" <Ns**********@characoid.com> wrote:

[ Guys! Please learn to snip... ]
"Keith Thompson" <ks***@mib.org> wrote in message
I prefer an explicit comparison:

if (strcmp(string1, string2) != 0) ...

If the function's name implied that it tests whether the arguments
differ, I might feel differently about it.


What do you think strcmp stands for? I usually think of it as "string
compare", meaning "do the strings compare?". By that sense, the function's
name implies that it tests whether the arguments differ.


OTOH, it's also possible to think of it as "_how_ do these strings
compare?", the answer being either "s1 is smaller", "they're equal", or
"s2 is smaller".
Since this is the meaning that the Standard requires the function to
provide (no matter that _you_ only care, in a given line of code,
whether one of these three is true), I think it's the most appropriate
one.
if (!cap_issubset(inheritable,
cap_combine(target->cap_inheritable,

current->cap_permitted)))
goto out;


That's indented much too deeply for my taste. Are you using hard tabs
with a non-standard tabstop setting?

I might write:

if (!cap_issubset(inheritable,
cap_combine(target->cap_inheritable,
current->cap_permitted)))


It looked like this when I posted it. I used spaces, not tabs.


Either, IMO, is overly indented, but yours showed up at this end exactly
as far indented (the cap_combine under the 'l' of inheritable, and the
third line under the 'p' of cap_inheritable) as shown above, except that
it hadn't wrapped yet. Are you perhaps using a proportional font for
reading Usenet? If so, consider that spaces in proportional fonts are
generally about half as wide as those in fixed-width fonts.

Richard
Nov 14 '05 #75

P: n/a
On 03 Jan 2005 13:44:57 EST, "Natt Serrasalmus"
<Ns**********@characoid.com> wrote:

"Alan Balmer" <al******@att.net> wrote in message
news:f0********************************@4ax.com.. .
On 29 Dec 2004 21:58:30 EST, "Natt Serrasalmus"
<Ns**********@characoid.com> wrote:
the C idiom that was established with the C standard library.
The idiom I am referring to is that functions should return a value that
answers the question "Did anything go wrong and if so what was it?"
But that's just not true, except for the I/O functions. Most others
return some value as a result, not as a diagnostic.

I will write "if (a)" providing 'a' is a boolean.


As I pointed out in other posts, there is no boolean in C. Logical
expressions are evaluated as integers having a value of zero or non-zero.

You keep repeating this as if it is something you just learned ;-)
Boolean is a concept, not just a data type. You can use truth values
in C (and even call them Booleans in C99) without ever knowing the
integer values they represent.
If not, I will write
if (a != 0). If that bothers you, so be it.


If a is an integer, then it can have a value of zero or non-zero and
therefore can be treated as if it were a boolean value. Therefore, why go to
the trouble of doing the comparison?


My programs are written not only for the compiler to understand, but
for a human to understand. Variables are used in a way which is
natural to the problem domain. Pretending an integer is a truth value,
or vice versa, does not contribute to understanding.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 14 '05 #76

P: n/a
infobahn <in******@btinternet.com> wrote:
Natt Serrasalmus wrote:

When a logical expression is evaluated in C, it is evaluated as an integer
expression and it determines if the integer is zero or non-zero. Sounds
boolean doesn't it? Two states: either zero or non-zero.


You missed my point. Consider the following function names:

int IsPrinterReady(PRINTER *);
int IsLeapYear(int);
int Sum(int *, size_t);
int HasTransferCompleted(DATA *);
int OpenDatabase(DB *);

All these functions return int. It is quite obvious, however, to
the experienced, intelligent, or just plain common-sense eye that
three of the five are designed to answer a Boolean question. That
is, they return a number representing 'true' or a number representing
'false'. The others do not.


Beg to differ. IsLeapYear(), obviously yes. IsPrinterReady(), yes. But I
could imagine HasTransferCompleted() to write the address of the next
completed data buffer through its argument, and return the number of
unprocessed complete data buffers. In all these cases, except perhaps
IsLeapYear() if I'm certain I'm not going to pass dates before 1572, I'd
certainly want to read the specs before using them no matter how obvious
they look.
However assuming that you could have provided a more complicated example, I
would have expected it to be similar to the form in the re-posted (pseudo)
code example 1. Having given that example, you should have no trouble seeing
how early exits from functons improve the readability of the code.


You have certainly demonstrated how early exits from functions appear
to encourage long, poorly written, rambling functions.


No, he hasn't. He's demonstrated that muddle-headed programmers find
themselves encouraged to do so by whatever style they use, but that's
hardly surprising.
They should be up to speed on the language.


I agree, but nobody should have to remember precedence tables.


Oh? We shouldn't remember that * goes above +, and both above &&? It's
not generally necessary to remember the details surrounding &, &&, = and
==, but I'd certainly want any competent programmer to remember the
basics.

Richard
Nov 14 '05 #77

P: n/a

In article <11**********************@c13g2000cwb.googlegroups .com>, jd*********@yahoo.com writes:

Please provide proper attributions when you quote on Usenet. For someone
so concerned with imposing consistency, you're observing rather poor
netiquette.
[True Style] is a common style, but its mindshare seems to
be diminishing.
I'll believe you, though it saddens me. Pursuing the analogy
with English, frequent misspellings eventually make their
way into the dictionary, but that doesn't make misspelling
right.


Unfortunately, your understanding of English is flawed, so your
analogy holds no water. English "misspellings" are neither right nor
wrong; they may be common or uncommon, and they may be accepted or
not by a particular group, but there is no English language standard,
and no generally-recognized arbiters of the language.

To return to an example from your previous post: putting periods and
commas before closing quotation marks, regardless of their proper
scope in the sentence, does not "improve" your writing (or anyone
else's). It shows that you are willing to kowtow to a particular
convention - and a pointless one at that, one which was invented
solely to preserve fragile lead type. Since few documents are set in
lead type these days, there's no justification for continuing that
convention. Contrary to your claim, I think you'll find no evidence
that preserving this convention for the sake of "consistent punctua-
tion" has any benefit whatsoever for readability. Few readers would
even notice.
The True Style was never universally agreed, of course,
but was in very widespread use among the most elite C
programmers.
So you say. Do you have any actual empirical evidence to support
this? What's your rubric for determining membership in "the most
elite C programmers"? What constitutes "very widespread use"?
Good and bad code may be written in any
style of course, but I'm sure there is (was?) a strong
positive correlation between coding in True Style and
positive traits like clarity and modularity.
What an odd thing to be sure of. I'd rather think it's just the
sort of question that tends to produce unfounded belief.
(I'm not
saying True Style is intrinsically conducive to good
coding practice, just that those who use it tend to have
learned from or emulate the Masters.)
Ah, Cargo Cult Programming.
(1) I was mostly observing this style already, a major
exception being brace placement. I was writing
}
else
{
but in True Style this is written
} else {
The second form is simply better than the first! The former
form disconnects the keyword "else" from both its antecedent
and postcedent
Nonsense. I can read more than one line at a time, and so can
every programmer I've ever known.
and is distracting to read.
For you, perhaps. I've not heard this complaint from anyone else.

What constitutes a "distraction" in this context? Presumably the
reader is concerned primarily with semantics - what algorithm the
source expresses - and so a distraction would be some feature of
the source which called attention away from semantics; in short, a
syntactic element which caught the reader's attention. I suspect
then that "distraction" is equivalent to syntactic surprise - which
leads to the unsurprising conclusion that what is "distracting to
read" is any style the reader is not accustomed to.
Also it wastes
two lines on the screen compared with the latter form, and this
is a "big deal." The left-braces in Non-true code use up
considerable vertical space and therefore more scrolling is
needed to understand a function. Smaller fonts might alleviate
this problem, but that's not an option for those of us
with poor eyesight.
By this argument, you should eliminate whitespace wherever possible.

The "compact representation" argument is a non-starter in style wars.
Clearly either extreme is unacceptable, but that tells us nothing
about the wide range of reasonable alternatives. There is a wealth of
research on the effects of layout on readability (which I suspect few
style police have read), but what I've read of it indicates - again
unsurprisingly - that differences among readers and aspects of
particular documents are far too important to make any very specific
rules generally applicable.

In this particular case, there's certainly ample anecdotal evidence
that plenty of potential source-code readers prefer the additional
vertical whitespace to compactness.
(2) I was proud to emulate the style of so many Masters.
Cargo cult.
(3) As I examined various software I noticed the strong correlation
between True Style and good traits like clarity and modularity.
Observer error, I suspect. Did you do any formal analysis to prove
that this observation was in fact present? People are notoriously
poor at accurately observing correlations.
(4) Whitespace arrangement isn't all that important but
uniformity would be convenient.


What sort of convenience does it provide?

--
Michael Wojcik mi************@microfocus.com

Auden often writes like Disney. Like Disney, he knows the shape of beasts --
(& incidently he, too, might have a company of artists producing his lines) --
unlike Lawrence, he does not know what shapes or motivates these beasts.
-- Dylan Thomas
Nov 14 '05 #78

P: n/a
Richard Bos wrote:
infobahn <in******@btinternet.com> wrote:

.... snip ...

I agree, but nobody should have to remember precedence tables.


Oh? We shouldn't remember that * goes above +, and both above &&?
It's not generally necessary to remember the details surrounding
&, &&, = and ==, but I'd certainly want any competent programmer
to remember the basics.


As far as I am concerned, multiplicative has precedence over
additive which has precedence over logical will do. Anything
further should be explicitly indicated with the use of the all
purpose parentheses. The mere existence of further levels in C is
a fault IMNSHO. Yes, I know there are no precedence levels in C,
just Backus-Naur descriptions.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #79

P: n/a
In article <41***************@yahoo.com>,
CBFalconer <cb********@yahoo.com> wrote:
Richard Bos wrote:
infobahn <in******@btinternet.com> wrote:

... snip ...

I agree, but nobody should have to remember precedence tables.


Oh? We shouldn't remember that * goes above +, and both above &&?
It's not generally necessary to remember the details surrounding
&, &&, = and ==, but I'd certainly want any competent programmer
to remember the basics.


As far as I am concerned, multiplicative has precedence over
additive which has precedence over logical will do. Anything
further should be explicitly indicated with the use of the all
purpose parentheses. The mere existence of further levels in C is
a fault IMNSHO. Yes, I know there are no precedence levels in C,
just Backus-Naur descriptions.


I always wanted to write down a grammar that allows exactly those C
expressions that I find acceptable and disallows those that I don't like
(for example "a << b + c" - is it (a << b) + c or a << (b + c)? ) Never
found the time for it, but it shouldn't be too difficult.
Nov 14 '05 #80

P: n/a
On Tue, 04 Jan 2005 21:44:53 +0000, Christian Bau
<ch***********@cbau.freeserve.co.uk> wrote:
I always wanted to write down a grammar that allows exactly those C
expressions that I find acceptable and disallows those that I don't like
(for example "a << b + c" - is it (a << b) + c or a << (b + c)? ) Never
found the time for it, but it shouldn't be too difficult.


The problem I find is that what I want the expression to do
'intuitively' depends on the context. The precedence I do find awkward
is the && and &, I often want to do something like:

if (flags & FLAG_1 && flags & FLAG_2)

meaning do the bit operations first, and dislike the extra parentheses I
have to put in to force that. As I recall in the rationale for C89
there was something about "we really wanted to change some of these but
it would break too much code".

Chris C
Nov 14 '05 #81

P: n/a
On Tue, 04 Jan 2005 21:26:42 GMT, CBFalconer
<cb********@yahoo.com> wrote:
As far as I am concerned, multiplicative has precedence over
additive which has precedence over logical will do. Anything
further should be explicitly indicated with the use of the all
purpose parentheses. The mere existence of further levels in C is
a fault IMNSHO. Yes, I know there are no precedence levels in C,
just Backus-Naur descriptions.


I've tried to write a precedence-based parser for C expressions. It's
all fine apart from the ternary operator, as far as I could determine
nothing makes that come out right (I tried all combinations of left and
right precedence, and none gave the right answer for a ? b ? c : d : e).
Which was annoying since I did not want to use a top-down BNF parser for
it. I eventually 'solved' it with a hack which did special things with
the ternary operator...

Chris C
Nov 14 '05 #82

P: n/a
Richard Bos wrote:

infobahn <in******@btinternet.com> wrote:
You missed my point. Consider the following function names:

int IsPrinterReady(PRINTER *);
int IsLeapYear(int);
int Sum(int *, size_t);
int HasTransferCompleted(DATA *);
int OpenDatabase(DB *);

All these functions return int. It is quite obvious, however, to
the experienced, intelligent, or just plain common-sense eye that
three of the five are designed to answer a Boolean question. That
is, they return a number representing 'true' or a number representing
'false'. The others do not.
Beg to differ. IsLeapYear(), obviously yes. IsPrinterReady(), yes. But I
could imagine HasTransferCompleted() to write the address of the next
completed data buffer through its argument, and return the number of
unprocessed complete data buffers.


Wow! I must be more thoughtful about function-naming in the future.
My idea of "obvious" is clearly not in line with other people's idea
of "obvious". I would have encapsulated the functionality you describe
using a function named something like WriteNextDataBufferAddress().
I am not sure that I'd necessarily get such a function to return
a number of unprocessed buffers; I think I'd prefer to return a
status code.
In all these cases, except perhaps
IsLeapYear() if I'm certain I'm not going to pass dates before 1572, I'd
certainly want to read the specs before using them no matter how obvious
they look.
It would be irresponsible to do otherwise, no matter what the
function is called.
Having given that example, you should have no trouble seeing
how early exits from functons improve the readability of the code.


You have certainly demonstrated how early exits from functions appear
to encourage long, poorly written, rambling functions.


No, he hasn't. He's demonstrated that muddle-headed programmers find
themselves encouraged to do so by whatever style they use, but that's
hardly surprising.


Correction accepted.
They should be up to speed on the language.
I agree, but nobody should have to remember precedence tables.


Oh? We shouldn't remember that * goes above +, and both above &&?


One eventually absorbs this information anyway, without particularly
having to go to the trouble of learning it. There is a difference
between knowing a tiny fraction of the precedence "rules" (there
aren't any, really - they just fall out of the grammar; but I know
you know that) and knowing the whole table, operator-perfect.
It's
not generally necessary to remember the details surrounding &, &&, = and
==,
Precisely my point.
but I'd certainly want any competent programmer to remember the
basics.


I would not judge the competence of a C programmer by his ability to
remember a couple of facts from p53. I might, however, judge his
incompetence from his inability to remember those same facts!

Off the top of my head, I can't remember which has higher precedence,
? : or =. If I can't, then I suspect that a good few other people
can't, either - so I'll use parentheses to clarify my meaning, rather
than look it up. That way, I save N + 1 lookups - one for me, and N
for those reading my code whose memory is as bad as mine.
Nov 14 '05 #83

P: n/a
Keith Thompson wrote:

infobahn <in******@btinternet.com> writes:
[...]
Even before C introduced _Bool, it was possible to use ints (and
other integer types) as Boolean values, by the simple method of only
ever writing a 0 or a 1 to them.


Actually, you can implement Boolean values with ints by writing zero
or non-zero to them, and by referring to them only in ways that work
the same way for any non-zero value. Treating 2 or -1 as "true" is
perfectly valid.


True enough, but I always prefer to be a little stricter about such
matters than is perhaps common amongst typical C programmers. A
failing of mine, no doubt.
Nov 14 '05 #84

P: n/a
Chris Croughton <ch***@keristor.net> writes:
The problem I find is that what I want the expression to do
'intuitively' depends on the context. The precedence I do find awkward
is the && and &, I often want to do something like:

if (flags & FLAG_1 && flags & FLAG_2)

meaning do the bit operations first, and dislike the extra parentheses I
have to put in to force that.


The above is equivalent to
if ((flags & FLAG_1) && (flags & FLAG_2))
I don't know why you seem to think it isn't.
--
"Given that computing power increases exponentially with time,
algorithms with exponential or better O-notations
are actually linear with a large constant."
--Mike Lee
Nov 14 '05 #85

P: n/a
CBFalconer <cb********@yahoo.com> wrote:
Richard Bos wrote:
infobahn <in******@btinternet.com> wrote:

... snip ...

I agree, but nobody should have to remember precedence tables.


Oh? We shouldn't remember that * goes above +, and both above &&?
It's not generally necessary to remember the details surrounding
&, &&, = and ==, but I'd certainly want any competent programmer
to remember the basics.


As far as I am concerned, multiplicative has precedence over
additive which has precedence over logical will do. Anything
further should be explicitly indicated with the use of the all
purpose parentheses.


You write

a = (b + (c[1]));

? Methinks you know more than you realise you know.

Richard
Nov 14 '05 #86

P: n/a
On Tue, 04 Jan 2005 21:22:35 -0800, Ben Pfaff
<bl*@cs.stanford.edu> wrote:
Chris Croughton <ch***@keristor.net> writes:
The problem I find is that what I want the expression to do
'intuitively' depends on the context. The precedence I do find awkward
is the && and &, I often want to do something like:

if (flags & FLAG_1 && flags & FLAG_2)

meaning do the bit operations first, and dislike the extra parentheses I
have to put in to force that.


The above is equivalent to
if ((flags & FLAG_1) && (flags & FLAG_2))
I don't know why you seem to think it isn't.


Because I get the precedence wrong <g>. So, it seems, do a lot of
people (almost everywhere I've worked with a "coding style" has said to
put them in there). Wrong example, it's relational operators which are
the silly ones:

value & 0x1F == 3

evaluates the == first, which is silly because there is no time anyone
would sensibly want to apply a bit mask to the result of a boolean
operation, it's all the other way round.

Chris C
Nov 14 '05 #87

P: n/a
Ben Pfaff wrote:
Chris Croughton <ch***@keristor.net> writes:
The problem I find is that what I want the expression to do
'intuitively' depends on the context. The precedence I do find
awkward is the && and &, I often want to do something like:

if (flags & FLAG_1 && flags & FLAG_2)

meaning do the bit operations first, and dislike the extra
parentheses I have to put in to force that.


The above is equivalent to
if ((flags & FLAG_1) && (flags & FLAG_2))
I don't know why you seem to think it isn't.


I don't think it is the "isn't" that bothers him, it's the
uncertainty, lacking the parentheses. I would always use your
version of the expression.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #88

P: n/a
"Natt Serrasalmus" <Ns**********@characoid.com> writes:
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.


The reason given here doesn't qualify as objective IMO. I find it
just as easy to match braces in code using K&R bracing; easier,
in many cases.

Furthermore, the idea that ease of brace matching is the only factor
(for brace placement) that matters for code quality is itself
subjective. For some quality metrics, it is outright false.

Nov 14 '05 #89

P: n/a
infobahn <in******@btinternet.com> wrote:
Richard Bos wrote:

infobahn <in******@btinternet.com> wrote:
You missed my point. Consider the following function names:

int IsPrinterReady(PRINTER *);
int IsLeapYear(int);
int Sum(int *, size_t);
int HasTransferCompleted(DATA *);
int OpenDatabase(DB *);

All these functions return int. It is quite obvious, however, to
the experienced, intelligent, or just plain common-sense eye that
three of the five are designed to answer a Boolean question. That
is, they return a number representing 'true' or a number representing
'false'. The others do not.


Beg to differ. IsLeapYear(), obviously yes. IsPrinterReady(), yes. But I
could imagine HasTransferCompleted() to write the address of the next
completed data buffer through its argument, and return the number of
unprocessed complete data buffers.


Wow! I must be more thoughtful about function-naming in the future.
My idea of "obvious" is clearly not in line with other people's idea
of "obvious".


Let's put it this way: if pressed, I'd guess that that function did what
you intended it to do. If not pressed, though, I wouldn't assume unless
the context was entirely clear. I wouldn't recommend that you change the
function's name; I _would_ recommend that people using those or any
other function take care with their assumptions.
> They should be up to speed on the language.

I agree, but nobody should have to remember precedence tables.


Oh? We shouldn't remember that * goes above +, and both above &&?


One eventually absorbs this information anyway, without particularly
having to go to the trouble of learning it. There is a difference
between knowing a tiny fraction of the precedence "rules" (there
aren't any, really - they just fall out of the grammar; but I know
you know that) and knowing the whole table, operator-perfect.


You'd be surprised at how much people do know. The most surprising ones
are the bitwise operators and the shifts; the precedence of the unary,
mathematical, equality and assignment operators is perfectly logical,
and so is that of the logical and ternary operators provided you don't
use them with the bitwise and shift ones.
but I'd certainly want any competent programmer to remember the
basics.


I would not judge the competence of a C programmer by his ability to
remember a couple of facts from p53.


Well, no; most of us don't need to know about universal character names,
after all.

Richard
Nov 14 '05 #90

P: n/a

"Tim Rentsch" <tx*@alumnus.caltech.edu> wrote in message
news:kf*************@alumnus.caltech.edu...
"Natt Serrasalmus" <Ns**********@characoid.com> writes:
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.


The reason given here doesn't qualify as objective IMO. I find it
just as easy to match braces in code using K&R bracing; easier,
in many cases.

Furthermore, the idea that ease of brace matching is the only factor
(for brace placement) that matters for code quality is itself
subjective. For some quality metrics, it is outright false.


I also agree that block braces should be at the
same indentation level. I have two reasons that
work for me:

1. My eye-sight is degraded; braces at the end
of a line are easily missed. Placing braces at
the same indentation level on their own lines
are easier for me to identify.

2. My C debugger knows nothing about C semantics;
it uses GNU-style stabs debugging information,
which only has references to original source line
number. The stabs info doesn't have anything about
statements, just line numbers. So, if I want to
set breakpoints at the start or end of a block,
the simplest way to do that is to click on the
opening or closing brace. If that brace is on
its own line, then I get the breakpoint set
correctly. If the brace line has other stuff on
it, then the breakpoint is set incorrectly (from
my viewpoint).

if(fubar == gorko) { /* line [1] */
geezer(krabbers);} /* line [2] */

In the above example, setting a breakpoint at
the start of the block requires pointing at
line [2] rather than line [1] which has the
opening brace. There is no way to set a
breakpoint on the closing brace.

if(fubar == gorko) /* line [1] */
{ /* line [2] */
geezer(krabbers); /* line [3] */
} /* line [4] */

Now I can set breakpoints on any of the
four lines, and my poor eye-sight can
easily distinguish the indentation levels
and where the block begins and ends.

For those of you with superior eye-sight,
please remember that someday someone else
with lesser visual acuity may have to
maintain the code and use a debugger with
the above limitations.

Hopefully there are enough C beautifiers
out there that can re-arrange code into
whatever style that best fits your own
requirements.

2 cents worth. Your mileage may vary.

--
----------------------------
Jeffrey D. Smith
Farsight Systems Corporation
24 BURLINGTON DRIVE
LONGMONT, CO 80501-6906
http://www.farsight-systems.com
z/Debug debugs your Systems/C programs running on IBM z/OS for FREE!

Nov 14 '05 #91

P: n/a
Richard Bos wrote:

infobahn <in******@btinternet.com> wrote:
Richard Bos wrote:

Oh? We shouldn't remember that * goes above +, and both above &&?


One eventually absorbs this information anyway, without particularly
having to go to the trouble of learning it. There is a difference
between knowing a tiny fraction of the precedence "rules" (there
aren't any, really - they just fall out of the grammar; but I know
you know that) and knowing the whole table, operator-perfect.


You'd be surprised at how much people do know. The most surprising ones
are the bitwise operators and the shifts; the precedence of the unary,
mathematical, equality and assignment operators is perfectly logical,
and so is that of the logical and ternary operators provided you don't
use them with the bitwise and shift ones.


I presume that, by "ternary operator", you mean the conditional
operator. You have certainly pinpointed the operators which are
most in need of parenthesisation by the paranoid^Wcautious.
but I'd certainly want any competent programmer to remember the
basics.


I would not judge the competence of a C programmer by his ability to
remember a couple of facts from p53.


Well, no; most of us don't need to know about universal character names,
after all.


That's most amusing. I can't believe a man of your calibre doesn't
know the precedence table on p53 of "The C Programming Language",
2nd edition.
Nov 14 '05 #92

P: n/a
"xarax" <xa***@email.com> writes:
[...]
I also agree that block braces should be at the
same indentation level. I have two reasons that
work for me:

1. My eye-sight is degraded; braces at the end
of a line are easily missed. Placing braces at
the same indentation level on their own lines
are easier for me to identify. [snip] if(fubar == gorko) { /* line [1] */
geezer(krabbers);} /* line [2] */

In the above example, setting a breakpoint at
the start of the block requires pointing at
line [2] rather than line [1] which has the
opening brace. There is no way to set a
breakpoint on the closing brace.

if(fubar == gorko) /* line [1] */
{ /* line [2] */
geezer(krabbers); /* line [3] */
} /* line [4] */


If you put *all* your braces at the ends of lines, of course you're
not going to be able to match them up easily. Here's how I'd write
it:

if (fubar == gorko) {
geezer(krabbers);
}

When I read this, I check that the indentation of the "}" matches the
indentation of the "if"; my only concern for the "{" is that there is
one.

I also use braces even for a single statement, as shown above (a habit
I picked up from Perl, which requires them).

I can't comment on the debugger issue you mentioned because I've never
run into it.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #93

P: n/a
Stephen Sprunk wrote:

"E. Robert Tisdale" <E.**************@jpl.nasa.gov> wrote in message
news:cr**********@nntp1.jpl.nasa.gov...
Stephen Sprunk wrote:
Apparently not, since I do it as well and I'm not European.
However, aren't ? and : parts of a ternary _operator_, not
_terminators_?

Would you write "a = b+ c;" or "a = b + c;" ? I prefer the latter,
and consider ? and : to be equivalent for formatting purposes.


Personally, I try to use the same punctuation rules
that are used for ordinary (mathematical) typesetting.


Except many operators in C are not ordinary mathematical symbols or may have
non-math meanings in certain contexts.
Here are my recommendations:

Terminators always follow immediately after an expression

x@ for all @ in {?, :, ,, ;}

and are followed by at least one white space.


I agree, except I don't consider ? and : to be terminators --


K&R refers to only to ; as a statement terminator.

--
pete
Nov 14 '05 #94

P: n/a
pete wrote:
Stephen Sprunk wrote:
E. Robert Tisdale wrote:
Stephen Sprunk wrote:

Apparently not, since I do it as well and I'm not European.
However, aren't ? and : parts of a ternary _operator_, not
_terminators_?

Would you write "a = b+ c;" or "a = b + c;" ? I prefer the latter,
and consider ? and : to be equivalent for formatting purposes.

Personally, I try to use the same punctuation rules
that are used for ordinary (mathematical) typesetting.


Except many operators in C are not ordinary mathematical symbols or may have
non-math meanings in certain contexts.

Here are my recommendations:

Terminators always follow immediately after an expression

x@ for all @ in {?, :, ,, ;}

and are followed by at least one white space.


I agree, except I don't consider ? and : to be terminators --


K&R refers to only to ; as a statement terminator.


Perhaps, but it isn't relevant.
The question mark, colon, comma and semicolon
are English punctuation marks first.
They are used as terminators in ordinary English.
The fact that they may be used to represent operators
in C programs should not matter.
I think that C programs are more readable
if they follow the same rules that are used
in ordinary [mathematical] typesetting.
Nov 14 '05 #95

P: n/a
Chris McDonald wrote:
After years of operating without any coding standards whatsoever, the
company that I recently started working for has decided that it might be a
good idea to have some. I'm involved in this initiative. [ . . . ]


Pleasing to see a helpful and sensible discussion here without a flurry of
vitriolic comments claiming it to be off-topic (perhaps it's just a matter
of the weekend or timezones).


Well, at least it *contains* C.
--
Derrick Coetzee
Nov 14 '05 #96

P: n/a
Michael Wojcik wrote:
Please provide proper attributions when you quote on Usenet.
For someone so concerned with imposing consistency, you're
observing rather poor netiquette.
Sorry. I often omit the attribution when the quote is
a paraphrased or consensus opinion, of limited relevance,
simply for context, or even in the interest of brevity.
Please note that readers who need the source can easily find
it, e.g. at Groups.Google. (Also posting at both Groups.Google
and Groups-Beta.Google seems to be broken these days. I
had to cut and paste to get the remark and attribution above.
Suggestions welcome, but be aware I post from Internet cafe.)

Also, to avoid disharmony, I often omit the attribution for a quoted
idea when I argue against the *idea*, but not against the ideator.

Speaking of harmony, let's please do avoid frivolous
objections or "straw-man" debates. I apologize for
any of my own comments which have been misunderstood --
My rhetoric gets a little too whimsical sometimes.
But if you *do* name the reference in an excerpt,
it is Netiquette to give quotee the benefit of his own
words. It is unreasonable to imply that jdallen2000
extrapolates a claim about the readability of
j } else {
to promote construction like
j char *s, *commap; int cnt;
j s = Begp; if (*s == '\0') return 0;
j for (cnt = 1; commap = index(s, ','); cnt++) {
j *commap = '\0'; plain_ups(s);
j s = commap + 1; while (*s == ' ') ++s;
j } plain_ups(s); return cnt;

I saw this sophomoric prank coming, and felt I had forestalled
it by posting the early rejoinder: ... with poor eyesight. (*Rarely*, I may even run statements
together on the same line, when the statements are
*very* similar, very short, and obviously coupled.)
Elsewhere:
with English, frequent misspellings eventually make their
way into the dictionary, but that doesn't make misspelling
right.

Your (understanding of English is flawed).


Hunh? What's your point? Are you one of the guys that
writes, "i saw the lite"? You seem to be from the laissez-faire
school, but your arguments shed more heet than lite.

I wrote: [True Style] was in very widespread use among the most elite C
programmers. ... proud to emulate the style of so many Masters.
Linus Torvalds also codes in True Style, so I don't think this
is just a Berkeley/Bell-Labs phenomenon.
Someone responded, and I paraphrase: No, this list of True Style programmers is not particularly
more or less skilled than [some other groups].
Really? Are you guys comparing yourselves to Bill Joy?
Of all the code *you*'ve examined, pick those that exhibited
the most skill and name the programmers.
What style did they use?

The best C code I've examined has been Unix kernels, shells, etc.
I realize this is a biased sample, but it would be fun to hear
from others. If your nominee did *not* write in True Style,
can you honestly say he's as good a programmer as nominees
like Linus Torvalds, Dennis Ritchie, and some of the BSD and
Sun programmers? I've not examined much of Chris Torek's
code but he'd qualify: what style does he use?

I also wrote: Although defense counsel continues to recommend `indent'
they offered no rebuttal to this point:
When I nest expressions of (x ? y : z), I tend to use
line-breaks and spacing to make the logic easy-to-see.
Maybe that's why the `indent' fans seemed to disparage
such nesting -- in their environment the helpful spacing
will tend to be expunged! Are we to conclude that the defendants are satisfied to use
only indent-approved spacing?


Still, no one has deigned to post a rebutter here.
Finally, I'll restore the spaces Google ate in the
code sample of the earlier post. Google seems to
be forcing short lines today, so you'll still have
to use a little imagination to see what the code
*really* looks like. A year ago I mentioned a stylistic deviation I use, and one
of the defense attorneys in the present case responded:
Blech.


Which of the following is more easily read?
Do be open-minded, setting aside any convention.

j My way:
j /*
j * Do a 3-D convolution.
j * Convolve in_sig with conv_k producing out_sig.
j * (Delivered code may be slightly different.)
j */
j for (x = in_sig->beg_x; x < in_sig->end_x;x++)
j for (y = in_sig->beg_y; y < in_sig->end_y;y++)
j for (z = in_sig->beg_z; z < in_sig->end_zz++) {
j val = 0;
j for (dx = conv_k->beg_x; dx < conv_kend_x; dx++) j for (dy = conv_k->beg_y; dy < conv_k->end_y; dy++)
j for (dz = conv_k->beg_z; dz < conv_k->end_z; dz++) {
j val += in_sig->dat[x+dx][y+dy][z+dz]
j * conv_k->dat[dx][dy][dz];
j }
j out_sig->dat[x][y][z] = val;
j }
j
... tends to hide the nesting [, but] FWIW, I *never*
omit the new-line before a for-body, even if it's the trivial
for-body (";"), so ... such for's will *always* be nested.


j
j
j "Approved" style:
j for (x = in_sig->beg_x; x < in_sig->end_x; x++)
j {
j for (y = in_sig->beg_y; y < in_sig->end_y; y++)
j {
j for (z = in_sig->beg_z; z < in_sig->end_z; z++)
j {
j val = 0;
j for (dx = conv_k->beg_x; dx < conv_k->end_x; dx++)
j {
j for (dy = conv_k->beg_y; dy < conv_k->end_y;
dy++)
j {
j for (dz = conv_k->beg_z; dz < conv_k->end_z;
dz++)
j {
j val += in_sig->dat[x+dx][y+dy][z+dz]
j * conv_k->dat[dx][dy][dz];
j }
j }
j }
j out_sig->dat[x][y][z] = val;
j }
j }
j }
j
Dearest regards, James Dow Allen (mail address: jamesdowallen at gmail)
j
j

Nov 14 '05 #97

P: n/a
On Thu, 06 Jan 2005 20:25:26 -0800, E. Robert Tisdale
<E.**************@jpl.nasa.gov> wrote:
K&R refers to only to ; as a statement terminator.
Perhaps, but it isn't relevant.
The question mark, colon, comma and semicolon
are English punctuation marks first.


So is dot (period, full stop). If I were writing C programs using
English punctuation rules I would write:

x = a. b? fred. bill + joe: foo. bar;

(it is conventional typography to put two spaces after a terminator, but
that looks even sillier).

For that matter, ! is also a terminator in English, do you also write
(! a)? Do you put the terminator inside the quotation marks, as style
guides for English say you should? I thank the gods (particularly God
Ritchie asd God Kernighan) that I don't have to maintain your code...
They are used as terminators in ordinary English.
Which is irrelevant, I am writing C not English.
The fact that they may be used to represent operators
in C programs should not matter.
I think that C programs are more readable
if they follow the same rules that are used
in ordinary [mathematical] typesetting.


They don't mean the same thing (what do ? and : mean in mathematical
typesetting anyway?). Certainly = doesn't mean the same as it does in
mathematics (something which trips a lot of mathematics students when
learning programming). Nor does ^ have its conventional meaning of
exponentiation.

C is not English. C is not mathematics. Different languages -- even
Real World(tm) ones, have different conventions for typography. Live
with it...

Chris C
Nov 14 '05 #98

P: n/a
Chris Croughton wrote:

On Thu, 06 Jan 2005 20:25:26 -0800, E. Robert Tisdale
<E.**************@jpl.nasa.gov> wrote:
K&R refers to only to ; as a statement terminator.


Perhaps, but it isn't relevant.
The question mark, colon, comma and semicolon
are English punctuation marks first.


So is dot (period, full stop). If I were writing C programs using
English punctuation rules I would write:

x = a. b? fred. bill + joe: foo. bar;

(it is conventional typography to put two
spaces after a terminator, but that looks even sillier).

For that matter, ! is also a terminator in English, do you also write
(! a)? Do you put the terminator inside the quotation marks, as style
guides for English say you should? I thank the gods (particularly God
Ritchie asd God Kernighan) that I don't have to maintain your code...
They are used as terminators in ordinary English.


Which is irrelevant, I am writing C not English.


That's a tedious point to keep repeating to E. Robert Tisdale.
Thank you.

--
pete
Nov 14 '05 #99

P: n/a

On Mon, 3 Jan 2005, Keith Thompson wrote:

jd*********@yahoo.com writes:
[snip]
for (x = in_sig->beg_x; x < in_sig->end_x; x++)
for (y = in_sig->beg_y; y < in_sig->end_y; y++)
for (z = in_sig->beg_z; z < in_sig->end_z; z++) {
val = 0;
for (dx = conv_k->beg_x; dx < conv_k->end_x; dx++)
for (dy = conv_k->beg_y; dy < conv_k->end_y; dy++)
for (dz = conv_k->beg_z; dz < conv_k->end_z; dz++) {
val += in_sig->dat[x+dx][y+dy][z+dz]
* conv_k->dat[dx][dy][dz];
}
out_sig->dat[x][y][z] = val;
}

[snip]

Unfortunately, we can't tell what kind of indentation you're using,
since group.google.com decided leading blanks aren't significant (a
violation of their "Don't be evil" policy IMHO). I've complained to
them about this and received what appears to be a form letter in
response.


Keep it up. There are humanoids reading the mail, but they won't
pay attention to you unless you write early and often. (I'm currently
engaged in a one-man letter campaign against their @-sensitive email
munging, which kills TeX source code even worse than blank-munging
kills C source code, and doesn't make rec.games.roguelike.development
much fun, either.)

HTH,
-Arthur
Nov 14 '05 #100

144 Replies

This discussion thread is closed

Replies have been disabled for this discussion.