Standard indentation?

11 views
Skip to first unread message

Russ Nelson

unread,
Dec 5, 1988, 2:27:22 PM12/5/88
to
I know, this is a religious question. However, I would like to know if
anyone has codified a standard for indentation of C programs?
--
--russ (nelson@clutx [.bitnet | .clarkson.edu])
To surrender is to remain in the hands of barbarians for the rest of my life.
To fight is to leave my bones exposed in the desert waste.

Frans van Otten

unread,
Dec 6, 1988, 5:27:14 AM12/6/88
to
In article <NELSON.88...@sun.soe.clarkson.edu> nel...@clutx.clarkson.edu writes:
>I know, this is a religious question. However, I would like to know if
>anyone has codified a standard for indentation of C programs?

There seems to be a de-facto standard, to which I stronly disagree. I'll
just explain my style:

#define then /* as white space; see below */

int func(a, b, c)
int a;
char b;
double c;
{ if (c > 3.0e10) printf("big\n");
while (a > 2)
{ putchar(b); putchar(c);
if (a > 10)
then putchar('1');
else putchar('2');
}
}

1. then must be defined (as white space) because the then-action
must be at the same level as the else-action. Some people dis-
agree with this, but look at it this way: *every* if-statement
can be rewritten into a switch-statement, and in that case, the
then-action and the else-action are at the same level:

if (expr) switch (expr)
then stat1; { default: stat1; break;
else stat2; case 0: stat2; break;
}

For shortness, if there is no else-action, you can always write
the then-part (with or without the 'then') on the same line as
the if (expr). This doesn't make the program less readable.

2. Indentation always by two spaces. A tab uses too much space.

3. Closing } always straight below opening {. It's easier to see
where the compound-statement ends.

4. Main rule: something *within* something else *always* indented.
You can easily see what belongs to what, which is the next state-
ment, etc.

I have been using this style for some years now. It has proved to me
that it is far more readable then any other style I ever saw. It has
proved useful debugging programs.
--
Frans van Otten
Algemene Hogeschool Amsterdam
Technische en Maritieme Faculteit
fra...@htsa.uucp

Usenet file owner

unread,
Dec 6, 1988, 7:54:48 AM12/6/88
to
in article <NELSON.88...@sun.soe.clarkson.edu>, nel...@sun.soe.clarkson.edu (Russ Nelson) says:
>
> I know, this is a religious question. However, I would like to know if
> anyone has codified a standard for indentation of C programs?

Last place I worked I drew up an informal internal C coding standard.
So, I'm sure there are plenty of internal coding standars that address.

K&R exhibits a consistent style, although they never really discuss it
in depth.

The closest I've seen to a "code"ified ;-) standard is GNU Emacs' C-mode
and description in the manual.

John H. Lawitzke UUCP: ...rutgers!mailrus!frith!fciiho!jhl
Michigan Farm Bureau ...decvax!purdue!mailrus!frith!fciiho!jhl
Insurance Group ...uunet!frith!jhl
"What?!? Real computing at an insurance company?!? AND in Michigan!?!"

Bjorn Engsig

unread,
Dec 6, 1988, 8:09:16 AM12/6/88
to
In article <NELSON.88...@sun.soe.clarkson.edu>, nel...@sun.soe.clarkson.edu (Russ Nelson) writes:
> I know, this is a religious question. However, I would like to know if
> anyone has codified a standard for indentation of C programs?
I have, my company standard is different, my previous company standard was
also different, my neighbour, etc. etc. etc

I wonder how long the discussion will live this time :-)
--
Bjorn Engsig, ORACLE Europe \ / "Hofstaedter's Law: It always takes
..!uunet!mcvax!orcenl!bengsig X longer than you expect, even if you
phone: +31 21 59 56 411 / \ take into account Hofstaedter's Law"

Dave Jones

unread,
Dec 6, 1988, 7:41:42 PM12/6/88
to
From article <NELSON.88...@sun.soe.clarkson.edu>, by nel...@sun.soe.clarkson.edu (Russ Nelson):

> I know, this is a religious question. However, I would like to know if
> anyone has codified a standard for indentation of C programs?

Yes, it is a religious question, and yes there have been standards
published.

My suggestion is not to worry about it during the design phase. Let
people use the style they are most comfortable with.

When it is time to turn a release, run all the sources through a
standard pretty-printer.

-=/ Larry Hastings /=-

unread,
Dec 7, 1988, 4:05:37 AM12/7/88
to
+-In article <NELSON.88...@sun.soe.clarkson.edu>,
+-nel...@sun.soe.clarkson.edu (Russ Nelson) wrote
+----------

|
| I know, this is a religious question. However, I would like to know if
| anyone has codified a standard for indentation of C programs?
|
+----------

Ain't no such animal; never will be. In fact, the UNIX program indent(1) has
more options than ls(1).
One thing I might suggest... if you're still deciding on whatever standard
YOU are going to use, you could lean towards something you could define with
indent options. THAT way, whenever you are looking at someone else's code,
(someone else who, of COURSE, completely disagrees with your style of indenting,
to the point of distraction) you can run it through indent so it will
suddenly become READABLE.
There is also cb(1), the original C pretty printer, which (I believe)
formats your program to the indentation standard that K&R uses. cb is generally
more available than indent. Also, cb won't change your code at all; indent
is known to mess around with comments and sometimes declarations.

--
/|\ /|\ .. . . . . . . . . . .
| |\| |\| .. . . . . . . . . . .
|/|\|/|\|/|| _ _ _ _ |_| _ _ |_ -__ _ _ARPA: fun...@ucscb.ucsc.EDU
| |/| |/|L_ (_\( ( (_/ | |(_\_) (_ || )(_)_)UUCP: *!ucbvax!ucscb!funkstr
\|/ \|/ larry / hastings _/ WORK: sun!acad!metaware!funkster
MetaWare Incorporated Disclaimer: It was a bad day.
"If any of your OSF force are caught or killed, the Secretary will deny any
knowlege of your activities." --from the new Mission: Impractical

Blair P. Houghton

unread,
Dec 7, 1988, 9:47:11 PM12/7/88
to
From article <NELSON.88...@sun.soe.clarkson.edu>, by nel...@sun.soe.clarkson.edu (Russ Nelson):
> I know, this is a religious question. However, I would like to know if
> anyone has codified a standard for indentation of C programs?

In My Egotistical Opinion, most people's C programs should be indented
six feet downward and covered with dirt.

--Blair
"#define foo baz"
-Obligatory obfuscation

Chris (i = --i++;) Quenelle

unread,
Dec 8, 1988, 4:40:29 AM12/8/88
to
In article <6...@htsa.uucp> fra...@htsa.UUCP (Frans van Otten) writes:
>
>#define then /* as white space; see below */
>
> if (a > 10)
> then putchar('1');
> else putchar('2');

Bravo!! Me Too!!
whenever the statements are blocks, I omit the then, though.
I vote strongly for this. The symmetry scans very easily for me.

--chris

-------------------------------------------------------------------------------
| Chris Quenelle | Smart Mailers -> cqu...@polyslo.CalPoly.EDU |
| Computer Systems Lab | Dumb Mailers -> !ucbvax!voder!polyslo!cquenel |
| Cal Poly State Univ. |-------------------------------------------------|
| San Luis Obispo, CA 93407 | My computer can beat up your computer. - Karl |
-------------------------------------------------------------------------------
We demand rigidly defined areas of doubt and uncertainty! -- Vroomfondel

Henry Spencer

unread,
Dec 8, 1988, 12:31:58 PM12/8/88
to
In article <10...@goofy.megatest.UUCP> djo...@megatest.UUCP (Dave Jones) writes:
>My suggestion is not to worry about it during the design phase. Let
>people use the style they are most comfortable with.

This ignores two problems: there are objective differences between styles
(it is *not* all just religion), and mixing styles is thoroughly bad. At
the very least, maintenance of old code should use the same style as the
old code, and multi-person projects should use a consistent style throughout.

>When it is time to turn a release, run all the sources through a
>standard pretty-printer.

Not a solution in the real world. Maybe if we had a telepathic pretty-
printer, but we don't. The programmer can still do a better job of
expressing his intent by doing it himself. Pretty-printers should be
used as a desperate last resort to make hideous code readable, not as
a routine method of cleaning up after lazy, self-centered programmers.
--
SunOSish, adj: requiring | Henry Spencer at U of Toronto Zoology
32-bit bug numbers. | uunet!attcan!utzoo!henry he...@zoo.toronto.edu

Doug Gwyn

unread,
Dec 9, 1988, 6:50:35 PM12/9/88
to
In article <65...@polyslo.CalPoly.EDU> cqu...@polyslo.CalPoly.EDU (Chris (i = --i++;) Quenelle) writes:
>>#define then /* as white space; see below */
>> if (a > 10)
>> then putchar('1');
>> else putchar('2');
>I vote strongly for this. The symmetry scans very easily for me.

It might be "easy", but it's wrong. Consider


if (a > 10)
then putchar('1');

something();
else putchar('2');
somethingElse();

Steve Bourne used a lot of (more elaborate and more correct) macro
definitions to make his C source code look more like Algol. He was
nearly universally cursed for having done so. Finally at least the
Bourne shell sources were straightened out; I don't know whether
the "adb" sources were ever fixed.

The consensus among experienced C users today is to not try to make
the source code look like it's written in some other programming
language, but rather to use C's native control constructs. That way
any person who knows C can immediately understand the control
structure of your source code, whereas if you introduce a lot of
special syntactic sugar, they would have to first puzzle that out
before they could reliably understand your source code.

Gerald Hawkins

unread,
Dec 9, 1988, 7:16:06 PM12/9/88
to
-
There are several main styles I have observed in my short experience with
C:

First, there is actually little disagreement on the basic idea of
indenting code within a loop. How many spaces to indent seems to be
purely a function of the width of your terminal or printer and the depth
of nested loops. Whether or not all indents should be the same amount is
never mentioned. I use TAB = 2 spaces for complex stuff and 4 spaces for
simple stuff.

The next major thing is where to put your '{' and '}'s. For example (pun
intended):

for(a = 1; a < 27; ++a)
{
...
...
}

OR,
for(a = 1; a < 27; ++a) {
...
...
}
Of these two, I prefer the former. It keeps all the matching pairs in
the same column, where they are easy to locate. It introduces more
whitespace, which makes the code look nicer and further identifies the
code within the loop. The latter condenses the code slightly. If one of
your objectives is "no function longer than 1 page", you may use the
latter form (but I won't like it).


Then there is the matter of how you handle do-while loops:

do
{
...
...
} while (x != EOF);
OR
do /* while (x != EOF) */
{
...
...
} while (x != EOF);
OR
x = 99; /* junk value so x doesn't equal EOF to start off */
while (x != EOF)
{
...
...
}

Here, the middle version is my favorite. If the code within the while is
long (25 - 75 lines) and there are lots of do and while statements, it
can be confusing matching them if you use the "self-documenting" approach
in the first fragment. The last fragment is crappy style, but I confess
to using it when I feel lazy. I would NOT use it at work for others to
read/review. BTW, the only difference between the 1st and 2nd examples
is that the second example has the condition repeated in a comment
prominently on the do - line.

Here is a confusing one:

Is it ever ok to use the form:
if (a = b * 2 + 39) /* intentional assignment within condition
*/
...

INSTEAD OF:
a = b * 2 + 39 /* more normal */
if (a)
...
I say "no!" The code is unsupportable. EVERYONE who ever reads it will
assume it is a trivial error (and perhaps try to correct it).

There are tons more items of style I am learning for the first time,
like--
If I have a code fragment which is used in only one place in one program,
but it is very independent code (doesn't depend heavily on surrounding
code), should I put that code into a function? If I do, it will add
(trivial) execution time, (trivial) additional stack usage, and (trivial)
size to the program.

When do you make the decision to use #define statements?

How much hard-coding is too much?

When do you decide to create a library (ie, anytime a function is shared
between two programs? Only when you are certain it is rock-solid? Only
if it is used by many programs and will probably be used by many more?

How do you decide how portable you want things to be?

Rainy Days and
Automatic Weapons Fire
Alway Get Me Down.

These opinions are mine.
Jerry. (je...@starfish.convergent.COM)
-----

Chris Torek

unread,
Dec 10, 1988, 3:22:18 PM12/10/88
to
In article <8...@starfish.Convergent.COM> je...@starfish.Convergent.COM

(Gerald Hawkins) writes:
>Is it ever ok to use the form:
[slightly edited]

> if (a = b * 2 + 39) /* intentional assignment within condition */
> ...
>INSTEAD OF:
> a = b * 2 + 39 /* more normal */
> if (a)
> ...
>I say "no!" The code is unsupportable. EVERYONE who ever reads it will
>assume it is a trivial error (and perhaps try to correct it).

Not necessarily everyone, but it is certainly a dubious construct.
This is especially true since you can write

if ((a = b * 2 + 39) != 0)
...

and make it clear that you did not accidentally omit one `='.
I still prefer two separate statements, with one exception:

/* typical sequence from Unibus drivers */
if (unit >= NFOO)
return (ENXIO);
ui = fooinfo[unit];
if (ui == NULL || !ui->ui_alive)
return (ENXIO);

Here one would like to write:

ui = fooinfo[unit];
if (unit >= NFOO || ui == NULL || !ui->ui_alive)
return (ENXIO);

but it is not safe to refer to (fooinfo[k] where k>=NFOO).
Hence:

if (unit >= NFOO || (ui = fooinfo[unit]) == NULL || !ui->ui_alive)
return (ENXIO);

This is rather borderline; if the contents of the `if' statement
were more complex I would be more solidly for it.
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain: ch...@mimsy.umd.edu Path: uunet!mimsy!chris

Doug Gwyn

unread,
Dec 10, 1988, 11:27:46 PM12/10/88
to
First, let's note that style issues are partly a matter of subjective
preference and partly objectively related to readability/maintainability.

In article <8...@starfish.Convergent.COM> je...@starfish.Convergent.COM (Gerald Hawkins) writes:

>First, there is actually little disagreement on the basic idea of
>indenting code within a loop. How many spaces to indent seems to be
>purely a function of the width of your terminal or printer and the depth
>of nested loops. Whether or not all indents should be the same amount is
>never mentioned. I use TAB = 2 spaces for complex stuff and 4 spaces for
>simple stuff.

I have a wonderful utility I developed at Geotronics called "retab"
that remaps tabs in a single pass. It makes it possible to deal with
code written according to tab conventions other than the local standard.
The EMACS "filter-region" or sam "|" operations make it possible to
apply this locally as needed.

>The next major thing is where to put your '{' and '}'s.

The way I look at it is, the {} are part of a compound statement, not
part of the control syntax. (This is in fact technically accurate.)

> do
> {
> ...
> ...
> } while (x != EOF);

Therefore, I use
do
whatever
while ( condition );
The style you show assumes there will be {} in the controlled statement.

>Is it ever ok to use the form:
> if (a = b * 2 + 39) /* intentional assignment within condition */

In code I originate (rather than patches I apply, where I try to follow
the pre-existing style), I ALWAYS distinguish between Boolean and integer
expressions and variables. Therefore, I would agree that the above is
poor style, but have no problem with using
if ( initialized = root_ptr != NULL )
I even typedef int bool so I can declare "initialized" as properly
Boolean. This slight language extension seems to me so essential for
robust coding that I have it in my standard header <std.h> (along
with #define true 1 and #define false 0). I don't use C's implicit
comparison-against-zero feature other than in the form
if ( boolean )
if ( !boolean )

>If I have a code fragment which is used in only one place in one program,
>but it is very independent code (doesn't depend heavily on surrounding
>code), should I put that code into a function?

If it performs a cleanly isolated, well-defined function, then it would
be best to code it as a genuine function (unless it is in a tight loop).
Otherwise, leave it in-line but set it off with block comments:
/*
* Now walk through the tree,
* converting all unmarked nodes to
* undefined name references.
*/
(Actually I use a different style for block comments, but the above
is commonly encountered.)

Don't forget that you can declare an inner block with {} and thereby
restrict the scope of locally-introduced variables. This can be
carried to an extreme, but it is often handy. (For instance, in the
code after the above block comment, one may want a temporary register
node pointer variable.)

>When do you make the decision to use #define statements?

#define "magic numbers", fixed limits, and other constant parameters.
By using symbolic names, it is easy to globally change the values later.

#define function-like or Boolean macros when an actual function would
be obvious overkill:
#define slave_busy (sfname != NULL && sfp == NULL)
#define FreeName(name) (name==0 ? (void)0 : (free(name),(void)(name=0)))

Try to avoid #ifdef system_type kind of code as much as possible.
It can really cut down on readability and correctness. Often the
best way to cope with system dependencies is to isolate them in
separate functions provided in separate source files, with the same
interface on all systems but necessarily a different implementation
for each different kind of system. Then one uses whichever system
interface module is appropriate at "make time", and doesn't have a
bunch of conditionalized code cluttering up the rest of the sources.

>How much hard-coding is too much?

Almost any is too much. It is proper to use explicit constants when it
is clear what they mean and that they can never need to be changed. For
example, assigning 0 or 1 to initialize a counter is proper. Assuming
that 03 is always the right character code for a keyboard interrupt
character (i.e. ASCII ctrl-C) is not proper.

>When do you decide to create a library (ie, anytime a function is shared
>between two programs? Only when you are certain it is rock-solid? Only
>if it is used by many programs and will probably be used by many more?

There are two main kinds of library. First is a library of generally-
useful programming support functions (essentially a standard C library
extension). Second is a product-specific library, normally used only
for large programming projects. For the first kind of library, you
should put some work into defining the function interface to be as
generally useful as possible, and provide a header for each package
of related functions you put in the library. Also supply manual pages.
For example, we have a directory /vld/include full of package headers
and a corresponding library /vld/lib/libVMB.a with all sorts of useful
functions, for example various random deviate generators, complex
arithmetic support, spline-smoothing of data, etc.

>How do you decide how portable you want things to be?

If it is not a LOT of extra work to make things maximally portable,
it should be done from the outset, unless you KNOW you're going to
throw the code away almost immediately (e.g. it's just an experiment
that cannot be patched up to make anything generally useful). You
will be glad you did when you need your programs on another system
unlike the one you developed them on.

Frank I. Reiter

unread,
Dec 11, 1988, 12:21:43 PM12/11/88
to
> Is if(a = b + c/4) (or something like this) legal ?

I do it all the time, but I do it like this :

|----
| if(a = b + c/4) /* Note assignment */
| whatever();
|----

Similarly I sometime code a switch like this :

|----
| switch(somevar) {
| case DELETE :
| deletesomething();
| /* Note fall-through */
| case NEXT :
| gotonextone();
| break;
| case ......
|----

--
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
Frank I. Reiter \ / UUCP: {uunet,ubc-cs}!van-bc!rsoft!frank
Langley, British Columbia / \ BBS: Mind Link @ (604)533-2312
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

Peter da Silva

unread,
Dec 11, 1988, 9:02:36 PM12/11/88
to
In article <8...@starfish.Convergent.COM>, je...@starfish.Convergent.COM (Gerald Hawkins) writes:
> Here is a confusing one:

> Is it ever ok to use the form:
> if (a = b * 2 + 39) /* intentional assignment within condition
> */

Yes, but probably only in the common idiom:

if((var = func(...)) == STATUS)
{

Such as:

if((fp = fopen(...)) == NULL)
{
perror(...);
return FAILURE;
}

or:

if((nextc = getchar()) != EOF)
{
...
}
--
Peter da Silva `-_-' Ferranti International Controls Corporation
"Have you hugged U your wolf today?" uunet.uu.net!ficc!peter
Disclaimer: I accept full responsibility for my typos. pe...@ficc.uu.net

Maarten Litmaath

unread,
Dec 12, 1988, 12:04:42 PM12/12/88
to
cqu...@polyslo.CalPoly.EDU (Chris (i = --i++;) Quenelle) writes:

\In article <6...@htsa.uucp> fra...@htsa.UUCP (Frans van Otten) writes:
\>
\>#define then /* as white space; see below */
\>
\> if (a > 10)
\> then putchar('1');
\> else putchar('2');

\Bravo!! Me Too!!
\whenever the statements are blocks, I omit the then, though.
\I vote strongly for this. The symmetry scans very easily for me.

For those who didn't get it: Chris' response is to be interpreted as sarcasm.
--
fcntl(fd, F_SETFL, FNDELAY): |Maarten Litmaath @ VU Amsterdam:
let's go weepin' in the corner! |ma...@cs.vu.nl, mcvax!botter!maart

Knudsen

unread,
Dec 12, 1988, 2:34:44 PM12/12/88
to
The new (4.0) version of Suntools includes some default editor
setups for C indentation and other style conventions.
Quite a few options.
I was gratified to see that I could set
it up for my own personal style, and in fact most of their defaults
agreed with mine. So there :-) :-).

(Of course, since I use Emacs exclusively, none of these settings
have a thing to do with the price of beer in Milwaukee.)
--
Mike Knudsen Bell Labs(AT&T) att!ihlpl!knudsen
"Lawyers are like nuclear bombs and PClones. Nobody likes them,
but the other guy's got one, so I better get one too."

Dave Jones

unread,
Dec 12, 1988, 7:54:07 PM12/12/88
to
There is a construct that is a little awkward using standard
(Pascal-like) structured statements: You want to read a value
from an external source, exit the loop if the value is a sentinal,
or process the value and continue if not a sentinal.

{
int ch;
do
{
ch = getchar();
if(ch != EOF) process(ch);
}
while (ch != EOF);
}


The expression !EOF gets evaluated twice. A compiler that
does common subexpression-removal and global flow-analysis
would fix things, but not all compilers are that smart.
Besides, I'm one of those old fashioned guys who wants the
compiler to do what I say. Or rather, I would like to be able
to say what I really want the compiler to do.

So we could do this:

for(;;)
{
int ch = getchar();
if(ch == EOF) break;
process(ch);
}

This is nice, in as much as it moves the declaration of ch one
level deeper. But it has the somewhat unstructured "break".
Still, not too bad. I prefer the following:


{ int ch;
while( (ch = getchar()) != EOF )
process(ch);
}


This says it almost literally, "While I get a ch that is not
a sentinal, I want to continue processing."

Ray Lubinsky

unread,
Dec 13, 1988, 10:48:14 AM12/13/88
to
In article <65...@polyslo.CalPoly.EDU>, cqu...@polyslo.CalPoly.EDU (Chris (i = --i++;) Quenelle) writes:
> In article <6...@htsa.uucp> fra...@htsa.UUCP (Frans van Otten) writes:
> >
> >#define then /* as white space; see below */
> >
> > if (a > 10)
> > then putchar('1');
> > else putchar('2');
>
> Bravo!! Me Too!!
> whenever the statements are blocks, I omit the then, though.
> I vote strongly for this. The symmetry scans very easily for me.

Hey! Why is this posted to comp.lang.c rather than
comp.lang.some-language-I-invented-yesterday-cause-its-neato?

Seriously, folks, having to wade through ad hoc "dialects" like this makes a
C programmer's stomach churn. Source code is a medium of communication to
other programmers as well as your future self when you have to maintain that
code. Offbeat dialects involving fake keywords just stand in the way of
comprehension.

(There, I feel better :-)

--
| Ray Lubinsky, UUCP: ...!uunet!virginia!uvacs!rwl |
| Department of BITNET: rwl8y@virginia |
| Computer Science, CSNET: r...@cs.virginia.edu -OR- |
| University of Virginia rwl%uv...@uvaarpa.virginia.edu |

Henry Spencer

unread,
Dec 13, 1988, 12:23:06 PM12/13/88
to
In article <91...@smoke.BRL.MIL> gw...@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>>How much hard-coding is too much?
>
>Almost any is too much. It is proper to use explicit constants when it
>is clear what they mean and that they can never need to be changed. For
>example, assigning 0 or 1 to initialize a counter is proper. Assuming
>that 03 is always the right character code for a keyboard interrupt
>character (i.e. ASCII ctrl-C) is not proper.

The policy we try to follow is that if you must hard-code a constant,
then it must be accompanied by a comment explaining why that particular
number is there.

Badri Lokanathan

unread,
Dec 13, 1988, 2:41:59 PM12/13/88
to
In article <14...@mimsy.UUCP>, ch...@mimsy.UUCP (Chris Torek) writes:
> I still prefer two separate statements, with one exception:
> (example follows.)

I am missing something here. Why is

a = expr; if (a == b) {statement}

preferable, in general, to

if ((a = expr) == b) {statement}

I think the second form is more concise and often more readable,
as per K & R II ed., pp. 16-17.
--
"I care about my fellow man {) ba...@ee.rochester.edu
Being taken for a ride, //\\ {ames,cmcl2,columbia,cornell,
I care that things start changing ///\\\ garp,harvard,ll-xn,rutgers}!
But there's no one on my side."-UB40 _||_ rochester!ur-valhalla!badri

Richard A. O'Keefe

unread,
Dec 13, 1988, 9:48:48 PM12/13/88
to
In article <10...@goofy.megatest.UUCP> djo...@megatest.UUCP (Dave Jones) writes:
>{ int ch;
> while( (ch = getchar()) != EOF )
> process(ch);
>}
>
>This says it almost literally, "While I get a ch that is not
>a sentinal, I want to continue processing."

I very much like embedded assignments, but that's a poor argument.
To exit a loop when you find a sentinel (that's two Es, no As), you can do
/* C version */ -- ADA version
for (;;) { loop
ch = getchar(); get(ch);
if (ch == EOF) break; exit when ch = sentinel;
process(ch); process(ch);
} end loop

I use the "while" version as an idiom for reading from a stream,
but it isn't as general a method as the use of 'break'.

Doug Gwyn

unread,
Dec 14, 1988, 12:57:13 AM12/14/88
to
In article <16...@valhalla.ee.rochester.edu> ba...@valhalla.ee.rochester.edu (Badri Lokanathan) writes:
>I am missing something here. Why is
>a = expr; if (a == b) {statement}
>preferable, in general, to
>if ((a = expr) == b) {statement}

Writing a whole bunch of unrelated actions on the same line of text isn't
particularly readable no matter what the actions are. Try

a = expression;

if ( a == b )
statement

There are several principles of style that apply to coding. One that is
relevant here is:
Actions that are thought of as separate tasks
should be separated visually.

If setting the value of `a' is conceptually only loosely related to
determining whether `a' now matches `b', then it is better to visually
separate these actions. On the other hand, if they are best thought
of as closely coupled, then combining them is appropriate:

for ( p = &qhead; (p = p->link) != &qhead; )
/* operate on node *p */

Sometimes, as in this example, it's really a "judgement call".

for ( p = qhead.link; p != &qhead; p = p->link )
/* operate on node *p */

is just about as acceptable. However, the following is poor:

p = qhead.link;
while ( p != &qhead )
{
/* operate on node *p */
p = p->link;
}

C's "for" statement was designed for bringing together visually
all the parts of loop control; use it for that. (A recent posting
showed a "for" statement whose three parts were not all involved
in controlling the loop; that violates the stylistic principle I
gave above.)

I agree with the recommendation that programmers read "The Elements
of Programming Style" by Kernighan and Plauger. There are other
books that give good stylistic advice, but that's the best starter.
Incidentally, this book doesn't use C in its examples, but the
principles are valid for most programming languages.

There isn't any way to automate good programming style, any more
than there is any good way to guarantee good program design.
Careful thought is essential.

Chris Torek

unread,
Dec 14, 1988, 2:00:04 AM12/14/88
to
>In article <14...@mimsy.UUCP> I wrote:
>>I still prefer ....

>I am missing something here. Why is
>
>a = expr; if (a == b) {statement}
>
>preferable, in general, to
>
>if ((a = expr) == b) {statement}

It is not. That is why I said `I prefer' rather than `it is better'.
The one that I believe is objectively worse than its alternatives is

if (l = r) ...

vs any of

0. l = r;
if (l) ...

1. l = r;
if (l != 0) ...

2. if ((l = r) != 0) ...

Rahul Dhesi

unread,
Dec 14, 1988, 11:51:28 AM12/14/88
to
In article <1988Dec13.1...@utzoo.uucp> he...@utzoo.uucp (Henry

Spencer) writes:
>The policy we try to follow is that if you must hard-code a constant,
>then it must be accompanied by a comment explaining why that particular
>number is there.

A suggestion: If you want to hard-code a constant, use a #define
anyway:

check_break() {
#define CTRL_C 3 /* ASCII control C */
if (keyscan() == CTRL_C)
...
}

A well-chosen name will make the code understandable. Any additional
information about the hard-coded value can be in a comment to the
#define itself. Scanning the source for all #defines will let you
locate all hard-coded constants with some confidence.

So I find the above code fragment preferable to the following:

check_break() {
if (keyscan() == 3) /* check for ASCII control C */
...
}
--
Rahul Dhesi UUCP: <backbones>!{iuvax,pur-ee}!bsu-cs!dhesi

Barry Margolin

unread,
Dec 14, 1988, 12:16:47 PM12/14/88
to
In article <1988Dec13.1...@utzoo.uucp> he...@utzoo.uucp (Henry Spencer) writes:
>The policy we try to follow is that if you must hard-code a constant,
>then it must be accompanied by a comment explaining why that particular
>number is there.

My rule of thumb is that if it needs a comment, it should be a
manifest constant, not a hardcoded literal. The name of the constant
then serves as self-documentation.

Barry Margolin
Thinking Machines Corp.

bar...@think.com
{uunet,harvard}!think!barmar

David Geary

unread,
Dec 14, 1988, 12:21:14 PM12/14/88
to
In article <65...@polyslo.CalPoly.EDU>, cqu...@polyslo.CalPoly.EDU (Chris (i = --i++;) Quenelle) writes:
> In article <6...@htsa.uucp> fra...@htsa.UUCP (Frans van Otten) writes:
> >
> >#define then /* as white space; see below */
> >
> > if (a > 10)
> > then putchar('1');
> > else putchar('2');
>
> Bravo!! Me Too!!
> whenever the statements are blocks, I omit the then, though.
> I vote strongly for this. The symmetry scans very easily for me.
^^^^^^^^^^^^^^^^^^^^^^^^^
For you maybe, but for someone else reading your code, maybe not.
One of the first things that students in my C class who are reformed
;-) Pascal programmers, want to do is this:

#define BEGIN {
#define END }

and a whole slew of other macros to make C look like pascal.

Let's say that Joe, Jim, Bob, and Phyllis are all programmers
working on a C project. Joe used to program in BASIC [sic],
Bob, Pascal, Jim, Fortran, and Phyllis ALGOL. So all of them
spend a day or two writing macros to make their C code look
like the language that their used to.

Then one day, Jim needs to debug Bobs code. He's not
debugging C, - he's debugging some wierd C/Pascal code, and
Jim doesn't know Pascal.

The moral of the story is:

1) When you write C code, you should try to make it as readable
for others as for yourself.
2) If you ever have to read (or - gasp - debug) someone else's
REAL C code - you're in trouble, because you don't KNOW C -
you know some weird C/(insert favorite language) dialect.
3) One of the best ways to learn C is to read someone else's C
code. (Even better, port it to a different machine). If
you don't write "real" C, you'll have a hell of a time
reading "real" C.

If you want to program in C - then program in C, not psuedo-C.


--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ David Geary, Boeing Aerospace, ~
~ #define Seattle RAIN ~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Andrew Koenig

unread,
Dec 14, 1988, 2:09:01 PM12/14/88
to
In article <8...@quintus.UUCP>, o...@quintus.uucp (Richard A. O'Keefe) writes:

> I very much like embedded assignments, but that's a poor argument.
> To exit a loop when you find a sentinel (that's two Es, no As), you can do
> /* C version */ -- ADA version
> for (;;) { loop
> ch = getchar(); get(ch);
> if (ch == EOF) break; exit when ch = sentinel;
> process(ch); process(ch);
> } end loop
>
> I use the "while" version as an idiom for reading from a stream,
> but it isn't as general a method as the use of 'break'.

Once upon a time I proposed an extension to the C syntax
that would allow a loop to have its (only) exit in the middle,
rather than at the beginning or end. In that syntax, the
example above would have looked like this:

do ch = getchar();
while (ch != EOF)
process(ch);

or, with braces:

do {
ch = getchar();
} while (ch != EOF) {
process(ch);
}

You will see that this syntax sort of merges

do S while (E);

and

while (E) S

into

do S while (E) S2

with the first two simply becoming degenerate forms of the third.

I couldn't sell anyone on the idea at the time. It's way too
late now, of course.
--
--Andrew Koenig
a...@europa.att.com

Dave Jones

unread,
Dec 14, 1988, 5:52:17 PM12/14/88
to
From article <33...@think.UUCP>, by bar...@think.COM (Barry Margolin):
...

>
> My rule of thumb is that if it needs a comment, it should be a
> manifest constant, not a hardcoded literal. The name of the constant
> then serves as self-documentation.
>

Your thumb is okay with me, so long as you add the proviso that
if the constant is only used in one place, its scope of definition
is restricted to that place. I'll try to say that in English.
I don't want the #define to be exiled to some #include file unless
it really is used all over the place. If it is local, keep it local.

Henry Spencer

unread,
Dec 15, 1988, 2:03:31 PM12/15/88
to
In article <51...@bsu-cs.UUCP> dh...@bsu-cs.UUCP (Rahul Dhesi) writes:
>>The policy we try to follow is that if you must hard-code a constant,
>>then it must be accompanied by a comment explaining why that particular
>>number is there.
>
>A suggestion: If you want to hard-code a constant, use a #define
>anyway...

Trouble is, often it's almost impossible to devise a meaningful name.
I'm not talking about hard-coding things like choice of control characters,
but about things like (in a function to concatenate two strings with a
'/' in between):

foo = malloc(strlen(a)+strlen(b)+2); /* 2 for '/' '\0' */

Now, what's a good name for that "2", and how does naming it improve
readability?
--
"God willing, we will return." | Henry Spencer at U of Toronto Zoology
-Eugene Cernan, the Moon, 1972 | uunet!attcan!utzoo!henry he...@zoo.toronto.edu

James Logan III

unread,
Dec 15, 1988, 8:54:05 PM12/15/88
to
In article <85...@alice.UUCP> a...@alice.UUCP (Andrew Koenig) writes:
#
# Once upon a time I proposed an extension to the C syntax
# [ explanation of construct deleted ]
#
# do {
# ch = getchar();
# } while (ch != EOF) {
# process(ch);
# }
#

It looks sort of strange, but when I read it I immediately
thought of a few recent situations where it would have been
handy.

-Jim
--
Jim Logan lo...@vsedev.vse.com
(703) 892-0002 uucp: ..!uunet!vsedev!logan
inet: logan%vsedev....@uunet.uu.net

RAMontante

unread,
Dec 16, 1988, 9:47:42 AM12/16/88
to
he...@utzoo.uucp (Henry Spencer) writes:
-
-Trouble is, often it's almost impossible to devise a meaningful name.
-I'm not talking about hard-coding things like choice of control characters,
-but about things like (in a function to concatenate two strings with a
-'/' in between):
-
- foo = malloc(strlen(a)+strlen(b)+2); /* 2 for '/' '\0' */
-
-Now, what's a good name for that "2", and how does naming it improve
-readability?

#define STRING_TERMINATOR_LENGTH 2

is descriptive, but I think only a fanatic Pascalist could love it. And
only somebody with a more-than-80-column display would want to use it.

more-fun-with-Henry's-signatures follows:

--
-"God willing, we will return." -Eugene Cernan, the Moon, 1972

I like it, but it's not obvious whether God understands "we" to mean
"Americans". Neil Armstrong had to go and get ecumenical with his
"...giant leap for mankind". And now it's those godless communists who
have a space station...

Barry Margolin

unread,
Dec 16, 1988, 12:23:07 PM12/16/88
to
In article <1988Dec15....@utzoo.uucp> he...@utzoo.uucp (Henry Spencer) writes:
>Trouble is, often it's almost impossible to devise a meaningful name.
>I'm not talking about hard-coding things like choice of control characters,
>but about things like (in a function to concatenate two strings with a
>'/' in between):
>
> foo = malloc(strlen(a)+strlen(b)+2); /* 2 for '/' '\0' */
>
>Now, what's a good name for that "2", and how does naming it improve
>readability?

I have a few ideas:

1) When I've done this in other languages, I've used something like
strlen("/") instead of the 2. Unfortunately, in C I'd still have to
say "+1", which I'd then want to comment with /* leave room for the
trailing null */, since I don't think there's an expression that will
return the total space taken up by a string. I like this because I
would expect a reasonable compiler to constant-fold the expression,
and it says exactly what the extra space is there for.

2) Define constants: #define PATH_DELIMITER "/"
#define ROOM_FOR_PATH_DELIMITER (strlen(PATH_DELIMITER))
#define ROOM_FOR_TRAILING_NULL 1

then use ROOM_FOR_PATH_DELIMITER+ROOM_FOR_TRAILING_NULL.
ROOM_FOR_TRAILING_NULL would probably be useful in other places if the
program does lots of concatenation like this. Those names are pretty
meaningful. If you're worried that strlen("/") won't be
constant-folded, put the 1 in the #define, with the expression in a
comment.

3) Word the comment differently: /* allocate room for the two strings,
a separator and trailing null */. This way, it doesn't sound as if
you're defining the 2, just explaining what the statement as a whole
is doing. The 2 is implicit, and doesn't really stand for anything.

Alan P. Curtis

unread,
Dec 16, 1988, 12:40:07 PM12/16/88
to
In article <8...@starfish.Convergent.COM> je...@starfish.Convergent.COM (Gerald Hawkins) writes:
+-
+There are several main styles I have observed in my short experience with
+C:
+
+The next major thing is where to put your '{' and '}'s:
+
+ for(a = 1; a < 27; ++a)
+ {
+ ...
+ ...
+ }
+
+OR,
+ for(a = 1; a < 27; ++a) {
+ ...
+ ...
+ }

OR (my favorite):

for(a = 1; a < 27; ++a)
{
...
...
}

+Of these two, I prefer the former.
I like mine because then you can say that the
"right way" to right a loop is
for(....)
statement;

where statement can be either
statement;
or
{
statements;
}

And life is simple again.
+Then there is the matter of how you handle do-while loops:
+
+ do
+ {
+ ...
+ ...
+ } while (x != EOF);
+OR
+ do /* while (x != EOF) */
+ {
+ ...
+ ...
+ } while (x != EOF);
+OR
+ x = 99; /* junk value so x doesn't equal EOF to start off */
+ while (x != EOF)
+ {
+ ...
+ ...
+ }
+
+Here, the middle version is my favorite.

Or in my system


do
{
...
...
} while (x != EOF);

Same reasons above.
I do NOT like the repeated statement comment idea, cause
it is hard to maintain. If I change while condition, *I*
must rember to change comment, else tis very bad.

+Here is a confusing one:
+Is it ever ok to use the form:
+ if (a = b * 2 + 39)
+INSTEAD OF:
+ a = b * 2 + 39 /* more normal */
+ if (a)
+ ...
+I say "no!" The code is unsupportable. EVERYONE who ever reads it will


>assume it is a trivial error (and perhaps try to correct it).

YES! if(a = 3*b) is FINE. Well, sortof.
provided you right == this way:
if(3*b == a) /* notice reversedness */

Then one cannot be confused.
Of course you do have to sometimes do:
if( (a=b) != 0)
in the simple assignment case.

apc
--
Alan P. Curtis | AT&T Bell Labs | a...@cblpe.ATT.COM

Rahul Dhesi

unread,
Dec 16, 1988, 4:13:28 PM12/16/88
to
In article <1988Dec15....@utzoo.uucp> he...@utzoo.uucp (Henry Spencer)
writes:
[But how about] about things like (in a function to concatenate

two strings with a '/' in between):

foo = malloc(strlen(a)+strlen(b)+2); /* 2 for '/' '\0' */

You are right. This is a valid exception to my suggestion, and it had
not occurred to me.

Wade Guthrie

unread,
Dec 16, 1988, 4:23:55 PM12/16/88
to
The sound of a programmer trying to read a C program flinging himself
against a wall.

In article <85...@alice.UUCP>, a...@alice.UUCP (Andrew Koenig) writes:
> do ch = getchar();
> while (ch != EOF)
> process(ch);
> or, with braces:
> do {
> ch = getchar();
> } while (ch != EOF) {
> process(ch);
> }

I really do not mean to flame this person, but the above constructions
are EXCEEDINGLY hard to read. I much perfer the method which already
exists:

while ( (c=getchar()) != EOF)
process(c);

because it is easier for humans to parse (not to mention the fact that it
requires less space.


Wade Guthrie
Rockwell International
Anaheim, CA

(Rockwell doesn't necessarily believe / stand by what I'm saying; how could
they when *I* don't even know what I'm talking about???)

Doug Gwyn

unread,
Dec 16, 1988, 5:16:26 PM12/16/88