Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Standard indentation?

13 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
to
In article <26...@cbnews.ATT.COM> a...@cbnews.ATT.COM (Alan P. Curtis) writes:
-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.

Who cannot be confused??

Joe English

unread,
Dec 16, 1988, 6:23:12 PM12/16/88
to

In article <24...@ssc-vax.UUCP> d...@ssc-vax.UUCP (David Geary) writes:

>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.
>

Which, being new C programmers, they don't really know how to do.
Just the other day I was helping an incorrigible Pascal programmer
debug some C code. She was only using C out of necessity, and had
done the following:

#define begin {
#define end; }

Which is not only wrong, but can be wrong in different ways depending
on the preprocessor!

I really think that it was a bad idea for K&R to mention that this
sort of thing is possible. Is their discussion of non-syntactic
macros in the 2nd edition, too?

/|/| "How do you convince your dermatologist
-----< | | that you're being sexually responsible?
O \|\| english%lip...@oberon.usc.edu

Richard A. O'Keefe

unread,
Dec 16, 1988, 7:46:29 PM12/16/88
to
he...@utzoo.uucp (Henry Spencer) writes:
>- 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 recently had a very similar problem. A *superb* "name" for that 2 is
sizeof "/"

Peter da Silva

unread,
Dec 16, 1988, 7:54:17 PM12/16/88
to
In article <33...@think.UUCP>, bar...@think.COM (Barry Margolin) writes:
> 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

How about sizeof "/"? Or does that return sizeof(char *)?
--
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.
Work: uunet.uu.net!ficc!peter, pe...@ficc.uu.net, +1 713 274 5180.
Home: bigtex!texbell!sugar!peter, pe...@sugar.uu.net.

Guy Harris

unread,
Dec 17, 1988, 12:02:13 AM12/17/88
to
>How about sizeof "/"? Or does that return sizeof(char *)?

No, it returns the number of bytes in the anonymous character array that
"/" is. K&R First Edition says "When applied to an array, the result is
the number of bytes in the array", and also

A string is a sequence of character surrounded by double quotes,
as in "...". A string has type "array of characters"...

so "/" is an array, and "sizeof", when applied to it, returns the number
of characters in it. The dpANS says much the same thing.

Unfortunately or fortunately, depending on how you look at it, 'sizeof
"/"' is 2, since the array in question has *two* characters - the '/'
and the '\0' at the end. This means that

strlen(a) + sizeof "/" + strlen(b)

happens to be the minimum number of characters that must be in the array
"buf" to make

strcpy(buf, a);
strcat(buf, "/");
strcat(buf, b);

work, since it counts both the "/" added by the first "strcat" and the
null left at the end; however

strlen(a) + sizeof "/" + strlen(b) + sizeof "/" + strlen(c)

is one more than the minimum number of characters that must be in the
array "buf" to make

strcpy(buf, a);
strcat(buf, "/");
strcat(buf, b);
strcat(buf, "/");
strcat(buf, c);

work. In this particular case it may not be worth worrying about since
it's only one character....

Rahul Dhesi

unread,
Dec 17, 1988, 10:24:59 AM12/17/88
to
In article <24...@ficc.uu.net> pe...@ficc.uu.net (Peter da Silva) writes:
>How about sizeof "/"? Or does that return sizeof(char *)?

I considered this and rejected it because it is misleading. We need 2
because one is for a '/' in the middle and one is for a trailing null,
not because we need two for just '/'. That "/" is a string and needs
two is not really the point, even though it gives the right answer.

The format I prefer most is actually:

strlen(a) + 1 + strlen(b) + 1

because it arranges the components of the expression in the right
order. (It also avoids the magic number 2. However, 1 is a magic
number here even though it isn't usually considered to be one.) It
would be nice to be able to say

strlen(a) + sizeof('/') + strlen(b) + 1

but unfortunately sizeof('/') is the same as sizeof(int).

One could also do

#define ONE_CHAR 1
#define TWO_CHARS 2

and then say things like:

strlen(a) + ONE_CHR + strlen(b) + ONE_CHR
strlen(a) + strlen(b) + TWO_CHARS

This sounds like the type of error undergraduates make when they are
first asked to use symbolic constants, but upon thinking I realize that
it could actually clarify the code quite a bit.

Steve Summit

unread,
Dec 17, 1988, 11:32:08 PM12/17/88
to
In article <1988Dec15....@utzoo.uucp> he...@utzoo.uucp (Henry Spencer) writes:
>...things like (in a function to concatenate two strings with a

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

You're all going to think I'm crazy, but I always write this as

... malloc(strlen(a)+1+strlen(b)+1) ...

to make it that much more obvious how the length is being
calculated. (A comment still helps.) This is merely a strict
application of Kernighan and Plaugher's adage, "Let the computer
do the dirty work." Why make the person reading the code
"decompile" the 2 into its constituents? (This example is
admittedly trivial, but in more complicated cases it can make a
big difference.)

C compilers can (and do) employ associativity and commutativity
to "fold" the two separate 1's into a single 2, at compile time,
so code like this is in no way less efficient. (I'm not sure how
much of the compiler's freedom to rearrange expressions is being
abrogated under ANSI C.)

Steve Summit
s...@adam.pika.mit.edu

Peter da Silva

unread,
Dec 18, 1988, 12:42:12 AM12/18/88
to
In article <7...@auspex.UUCP>, g...@auspex.UUCP (Guy Harris) writes:
> >How about sizeof "/"? Or does that return sizeof(char *)?
>
> No, it returns the number of bytes in the anonymous character array that
> "/" is.... [Which is 1+#chars, since the null is included]

#define STRLEN(s) (sizeof s - 1)
#define NULLEN 1

> strlen(a) + sizeof "/" + strlen(b) + sizeof "/" + strlen(c)

strlen(a) + STRLEN("/") + strlen(b) + STRLEN("/") +strlen(c) + NULLEN

Peter da Silva

unread,
Dec 18, 1988, 1:06:55 AM12/18/88
to
In article <3049@arcturus>, ev...@arcturus.UUCP (Wade Guthrie) writes:
> The sound of a programmer trying to read a C program flinging himself
> against a wall.

Is that like the sound of one hand clapping?

> 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);
> > }

This is a wonderful and clean extension to 'C' that solves the loop problem
once and for all!

> 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:

Only if you're not used to it. have you ever done extensive bourne-shell
or Forth programming, where this construct is a common idiom?

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

How about (in K&R indenting style, for consistancy):

do {
Ask question.
Get answer.
Categorise answer.
} while(answer != exit) {
Stuff...
switch(answer) {
...
}
And more stuff...
}

That is, what about the case where the first part of the loop is too complex
to fit in a while statement. Sure, you could put a break in, but isn't this
clearer? The existing while and do loops become special cases.

Steve Summit

unread,
Dec 18, 1988, 1:27:44 AM12/18/88
to

Was this suggestion supposed to include a :-) ? sizeof("/") is a
very poor substitute, in this case: it gets the right answer for
the wrong reason. (The '\0' the compiler counts in the string
constant "/" has little to do with the one which will be added
to the final, concatenated string.)

I once scratched my head over

kill(HUP, 1);

in a program which had modified /etc/ttys and wanted to tell
/etc/init (process 1) to re-read it. (This is more of a
unix-wizards than an info-c topic.) Funny thing: man 2 kill
says it's kill(pid, signal), and yet the code worked just fine.
(Spoiler: HUP just happens to be 1).

Steve Summit
s...@adam.pika.mit.edu

T. William Wells

unread,
Dec 18, 1988, 3:49:05 AM12/18/88
to
In article <1988Dec13.1...@utzoo.uucp> he...@utzoo.uucp (Henry Spencer) writes:
: 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.

My rule is this: any constant which is used, explicitly or implicitly,
more than once gets a define. Any tunable parameter gets a define.
Anything else stays a constant.

The first covers using a constant explicitly, as in defining a[256],
and implicitly as in a[255], when the 255 is there because 255 ==
sizeof(a) - 1. These should be something like a[SIZEA] and a[SIZEA-1],
respectively. However, it does not cover most uses of zero; zero
usually refers to either the first element of an array, a thing to be
converted to a null pointer, or a null character; all of which are
defined as part of the language and so don't require any definition
from me!

Some examples:

cnt = 0;
while (n) {
cnt += n & 1;
n >>= 1;
}

does not get any defines; the 1's are part of the problem definition.
On the other hand,

#define DREG_RDY 0x01

volatile char *dreg;

while (*dreg & DREG_RDY)
;

gets a define, the bit is defined in more than one place: the
hardware and the program.

---
Bill
{uunet|novavax}!proxftl!twwells!bill

John Sahr

unread,
Dec 18, 1988, 3:37:02 PM12/18/88
to
In article <3049@arcturus> ev...@arcturus.UUCP (Wade Guthrie) writes:
>In article <85...@alice.UUCP>, a...@alice.UUCP (Andrew Koenig) writes:
[suggesting a do-while syntax with the loop test in the middle]

>> do {
>> ch = getchar();
>> } while (ch != EOF) {
>> process(ch);
>> }
[deletions]
> ..........., but the above constructions

>are EXCEEDINGLY hard to read. I much perfer the method which already
>exists:
>
> while ( (c=getchar()) != EOF)
> process(c);
>Wade Guthrie

I think the point of Mr. Koenig's proposal was to handle larger loops than
the literal interpretation of his example indicated. Consider
>> do {
>> ch = getchar();
ch &= MASK;
ch = table_look_up[ch];
report_status(ch);


>> } while (ch != EOF) {
>> process(ch);

process2(ch);
process3(ch);
>> }

This too, is contrived, but is cleaner than jamming a bunch of statements
masquerading as an exit condition inside the test.
I'm not thrilled about the syntax, but it is an interesting idea. It
adds no keywords, breaks no code, resembles if-else syntax, and would solve
some "artistic style" problems I run into. Of course, one could use
goto-labels, breaks, or that interesting switch-case-for loop that showed
up in this group a while back.
Actually, my main objection with the syntax, I realize, is only the
indent/brace style, which differs from my own. (I won't tread any further
along that path...:-) )

Happy Holidays,

John

--
John Sahr, School of Elect. Eng., Upson Hall
Cornell University, Ithaca, NY 14853

ARPA: jo...@calvin.ee.cornell.edu; UUCP: {rochester,cmcl2}!cornell!calvin!johns

Mark A Terribile

unread,
Dec 18, 1988, 4:31:37 PM12/18/88
to
> [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.

Well, there is a way, although it's a little wordy and I don't know if I'd
do it myself.

foo = malloc( strlen( a ) + strlen( b ) + 2 * sizeof( char ) );

You may still have to note that the chars are '/' and null.
--

(This man's opinions are his own.)
From mole-end Mark Terribile

Blair P. Houghton

unread,
Dec 18, 1988, 6:15:02 PM12/18/88
to
In article <8...@calvin.EE.CORNELL.EDU> jo...@calvin.ee.cornell.edu.UUCP (John Sahr) writes:
>>In article <85...@alice.UUCP>, a...@alice.UUCP (Andrew Koenig) writes:
>[suggesting a do-while syntax with the loop test in the middle]
>
>I think the point of Mr. Koenig's proposal was to handle larger loops than
>the literal interpretation of his example indicated. Consider
>>> do {
>>> ch = getchar();
> ch &= MASK;
> ch = table_look_up[ch];
> report_status(ch);
>>> } while (ch != EOF) {
>>> process(ch);
> process2(ch);
> process3(ch);
>>> }
>
>This too, is contrived.

Pardon my two-cent kibbitz, but what's wrong with using the comma
operator to do that for which it is ideally suited?

I find the syntax as described above to be confusing. All of the
"ch =" statements are in the do-while loop, and all of the "process()"
statements are subsequent to the loop, no? No. But it seems so.
(Unless of course I've got it exactly backwards; It Can Happen, especially
when I'm entering a discussion I just now discovered.)

The K&R-conformant version would be:

do {
process(ch);
process2(ch);
process3(ch);
} while (
ch = getchar(),
ch &= MASK,
ch = table_look_up[ch],
report_status(ch),
ch != EOF
);

See? No muss, no fuss, sez who only curly-brackets get special
indentation, and you get to tell your grandchildren that you once
used the comma operator, which I consider one of the prime elegances
of the C language.

--Blair
",,,,"

Richard A. O'Keefe

unread,
Dec 19, 1988, 1:23:28 AM12/19/88
to
In article <85...@bloom-beacon.MIT.EDU> s...@adam.pika.mit.edu (Steve Summit) writes:
>In article <8...@quintus.UUCP> o...@quintus.UUCP (Richard A. O'Keefe) writes:
>>he...@utzoo.uucp (Henry Spencer) writes:
>>>- 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 recently had a very similar problem. A *superb* "name" for that 2 is
>> sizeof "/"
>
>Was this suggestion supposed to include a :-) ? sizeof("/") is a
>very poor substitute, in this case: it gets the right answer for
>the wrong reason. (The '\0' the compiler counts in the string
>constant "/" has little to do with the one which will be added
>to the final, concatenated string.)

Nope, it is the right answer for the right reason. The characters in
the byte array are exactly the characters which will be added. If you
were going to do sprintf(dest, "%s%s%s%s%s", a, "/", b, "/", c),
the size of dest would be strlen(a)+strlen(b)+strlen(c) + sizeof "//".
What I really prefer to do in a case like this is
#define arglen(x) (strlen(x)-2) /* strlen(x) - strlen("%s") */

static char fmt[] = "%s/%s/%s";
...
foo = malloc(sizeof fmt + arglen(a) + arglen(b) + arglen(c));
...
sprintf(foo, fmt, a, b, c);

Now if someone changes that to
static char fmt[] = "[%s.%s]%s;";
it still works.

Bjorn Engsig

unread,
Dec 19, 1988, 5:02:53 AM12/19/88
to

I've used the n-key very much lately :-(
--
Bjorn Engsig, ORACLE Europe \ / "Hofstadter's Law: It always takes
mcvax!orcenl!ben...@uunet.UU.NET X longer than you expect, even if you
phone: +31 21 59 56 411 / \ take into account Hofstadter's Law"

John H. Remmers

unread,
Dec 19, 1988, 7:44:47 AM12/19/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?
>
The "2" can be viewed as the incidental result of a bookkeeping operation:
a "+1" for the null terminator in a string concatenation, and a "+1" for
the extra '/' character. So naturally it's hard to name in an illumi-
nating way.

I always tell my students that bookkeeping is best left to the computer;
to improve readability, name the *concepts* and let the compiler sort out
the bookkeeping details. Hence the "2" probably shouldn't be in the
source code at all, named or otherwise.

The space requirement for a string concatenation is a frequently-needed
value; it's worth having a macro to represent it:

#define Catspace(s,t) (strlen(s) + strlen(t) + 1)

In terms of this, the malloc() call can be written:

foo = malloc(Catspace(s,t) + sizeof('/'));

thus making it explicit that you're concatenating two strings and
allocating one more byte for an extra character. Readability is
improved, and the question of naming the "2" never comes up.

Andrew Koenig

unread,
Dec 19, 1988, 9:37:13 AM12/19/88
to
In article <17...@buengc.BU.EDU>, b...@buengc.BU.EDU (Blair P. Houghton) writes:

> Pardon my two-cent kibbitz, but what's wrong with using the comma
> operator to do that for which it is ideally suited?

I can't use arbitrary statements with the comma operator:

int i, status, count = 0;
char temp[THINGSIZE];
do {
readthing(precious);
++count;
for (i = 0; i < THINGSIZE; i++)
temp[i] = precious[i];
status = munge(temp);
} while (status) {
for (i = 0; i < THINGSIZE; i++) {
if (temp[i] != precious[i])
printf ("munge changed element %d of line %d\n",
i, count);
}
}

As I said before, it's way too late to get anything like this
into C now. It's fun to think about, though.
--
--Andrew Koenig
a...@europa.att.com

Maarten Litmaath

unread,
Dec 19, 1988, 11:54:44 AM12/19/88
to
bar...@think.COM (Barry Margolin) writes:
\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.

How about the following?

sizeof "/"
--
fcntl(fd, F_SETFL, FNDELAY): |Maarten Litmaath @ VU Amsterdam:
let's go weepin' in the corner! |ma...@cs.vu.nl, mcvax!botter!maart

Maarten Litmaath

unread,
Dec 19, 1988, 3:46:44 PM12/19/88
to
rem...@m-net.UUCP (John H. Remmers) writes:
\...
\ #define Catspace(s,t) (strlen(s) + strlen(t) + 1)
\...
\ foo = malloc(Catspace(s,t) + sizeof('/'));

% cat c.c
main()
{
printf("%d\n", sizeof '/');
}
% cc c.c
% a.out
4
%

Mikael Pettersson

unread,
Dec 19, 1988, 10:02:59 PM12/19/88
to
In article <85...@alice.UUCP> a...@alice.UUCP (Andrew Koenig) writes:
>[edited]

>I can't use arbitrary statements with the comma operator:
> do {
> [read & munge & set status]

> } while (status) {
> for (i = 0; i < THINGSIZE; i++)
> if (temp[i] != precious[i])
> printf ("munge changed element %d of line %d\n", i, count);
> }

Watch:
#include <setjmp.h>
...
jmp_buf kappa;
do {
[read & munge & set status]
} while(status &&
(i=0,
setjmp(kappa),
i<THINGSIZE &&
(temp[i]!=precious[i] &&
printf("munge changed element %d of line %d\n", i, count),
++i,
longjmp(kappa) ),
1 )
);

Compiles and runs just fine :-)

>As I said before, it's way too late to get anything like this
>into C now. It's fun to think about, though.

Agreed.
BTW, I came up with the ideas for the above hack when I tried to figure out
a way to implement an `expression language' by translating it to plain old C.
It isn't pretty, but it would do if all you want is a quick and dirty
implementation of the new language.
--
Mikael Pettersson, Dept of Comp & Info Sci, University of Linkoping, Sweden
email: m...@ida.liu.se or ..!{mcvax,munnari,uunet}!enea!liuida!mpe

Peter da Silva

unread,
Dec 20, 1988, 10:43:09 AM12/20/88
to
In article <85...@alice.UUCP>, a...@alice.UUCP (Andrew Koenig) writes:
> As I said before, it's way too late to get anything like this
> into C now. It's fun to think about, though.

Is it? Petition your compiler writer. It should be a completely safe and
transparent extension to the existing syntax. The following should all
be valid:

do ... while(x); /* existing do/while, null while expr */
while(x) ... /* existing while, null do expr */
do ... while(x) ... /* full do/while */

The yaccoid BNF would be (since ";" is a valid statement):

dowhile : do WHILE(expr) statement
;

do : /* nothing */
| DO statement
;

If you can get a few compiler writers to put this in, it'll have a chance
of making it to the next version of 'C'. It reduces the complexity of the
language, too... replaces three constructs (do, while, and for) with one.
(yes, I am aware of the 'continue' problem, and I'm not suggesting removing
the for statement).

In fact, this could be declared an "editorial change" if you have the
brass.

Blair P. Houghton

unread,
Dec 20, 1988, 12:25:34 PM12/20/88
to
In article <85...@alice.UUCP> a...@alice.UUCP (Andrew Koenig) writes:
>In article <17...@buengc.BU.EDU>, b...@buengc.BU.EDU (Blair P. Houghton) writes:
>
>> Pardon my two-cent kibbitz, but what's wrong with using the comma
>> operator to do that for which it is ideally suited?
>
>I can't use arbitrary statements with the comma operator:

As others have recently reminded me, statement is not expression, and
expression is not statement. The comma operator separates expressions
only. My bad.

>As I said before, it's way too late to get anything like this
>into C now. It's fun to think about, though.

But wait! We could form a comittee, couldn't we? We could be the
abCDE, and meet and review and vote and review and meet and field input
from the input field and meet, review, vote...

--Blair
"...and end up with Fortro-C.scalispgol,
the scientific/systems/ai/graphic
programming language! All things
to all people. Damn the entropy!
Full redesign ahead!"

Karl Heuer

unread,
Dec 20, 1988, 4:36:29 PM12/20/88
to
In article <17...@buengc.BU.EDU> b...@buengc.bu.edu (Blair P. Houghton) writes:
>In article <85...@alice.UUCP> a...@alice.UUCP (Andrew Koenig) writes:
>>As I said before, it's way too late to get anything like this into C now.
>
>But wait! We could form a comittee, couldn't we? We could be the
>abCDE, and meet and review and vote and review and meet and field input
>from the input field and meet, review, vote...

(Yes, I realize you were being sarcastic. Nevertheless...)

Andrew is partially correct: it's way too late to get any fantastic new
features into C88 (__STDC__==1). However, it is not too soon to be thinking
about what should go into C99 (__STDC__==2). The correct procedure for such
future enhancements is to get them added as experimental extensions to
existing C compilers, so that the next ANSI C committee will have "existing
practice" to point to.

Karl W. Z. Heuer (ima!haddock!karl or ka...@haddock.isc.com), The Walking Lint

Dave Jones

unread,
Dec 20, 1988, 4:53:17 PM12/20/88
to
From article <26...@m2-net.UUCP>, by rem...@m-net.UUCP (John H. Remmers):
...

> The space requirement for a string concatenation is a frequently-needed
> value; it's worth having a macro to represent it:
>
> #define Catspace(s,t) (strlen(s) + strlen(t) + 1)
>

You are a candidate for SLMA (Silly Little Macros Anonymous).

There are no dues. Just get a sponsor and come to the meetings.
Take it One Day At A Time, and soon you will no longer be
sending innocent programmers poking through .h files in order
to figure out what "Catspace" means.

:-), in case you didn't guess.

But if you don't like the naked "1", how about this?

foo = malloc( strlen(s) + strlen(t) + sizeof('\0'));

Tells it all. And keeps the reader on track, not grepping around
for macros.

George Kyriazis

unread,
Dec 21, 1988, 12:31:42 AM12/21/88
to
In article <18...@solo11.cs.vu.nl> ma...@cs.vu.nl (Maarten Litmaath) writes:
>bar...@think.COM (Barry Margolin) writes:
>\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", ....

>
>How about the following?
>
> sizeof "/"

"/" is a pointer to a string containing a '/' and a '\0'. Therefore
it seems to me that sizeof "/" will return the same value as
sizeof( char * ).
Comments??


George Kyriazis
kyri...@turing.cs.rpi.edu
kyri...@ss0.cicg.rpi.edu
------------------------------

Maarten Litmaath

unread,
Dec 21, 1988, 11:55:32 AM12/21/88
to
kyriazis@rpics (George Kyriazis) writes:
\"/" is a pointer to a string containing a '/' and a '\0'. Therefore

\it seems to me that sizeof "/" will return the same value as
\sizeof( char * ).
\Comments??

% cat c.c
main()
{
printf("%d\n", sizeof "let's try out before we post");


}
% cc c.c
% a.out

29
%

Aha! sizeof(char *) == 29

Guy Harris

unread,
Dec 21, 1988, 12:57:24 PM12/21/88
to
>"/" is a pointer to a string containing a '/' and a '\0'.

"/" is not a pointer to a string; it is the string (i.e. an array of
"char") itself. In some, but not all, contexts, the array is converted
to a pointer to its first member; "argument of 'sizeof'" is not one of
those contexts. (Check your K&R, or your dpANS.)

>Therefore it seems to me that sizeof "/" will return the same value as
>sizeof( char * ).

This is, alas, apparently a mistake made by some C implementors; with
any luck, there'll be a conformance-testing suite for the ANS when it
comes out, and it will catch errors such as that.

Chip Salzenberg

unread,
Dec 21, 1988, 1:39:10 PM12/21/88
to
According to he...@utzoo.uucp (Henry Spencer):

>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' */

Not hard:

foo = malloc(strlen(a)+sizeof("/")+strlen(b));

--
Chip Salzenberg <ch...@ateng.com> or <uunet!ateng!chip>
A T Engineering Me? Speak for my company? Surely you jest!
"It's no good. They're tapping the lines."

Walter Bright

unread,
Dec 21, 1988, 2:35:36 PM12/21/88
to
In article <11...@goofy.megatest.UUCP> djo...@megatest.UUCP (Dave Jones) writes:
<foo = malloc( strlen(s) + strlen(t) + sizeof('\0'));
<Tells it all. And keeps the reader on track, not grepping around
<for macros.

But doesn't sizeof('\0') return sizeof(int), instead of sizeof(char)?
Remember, the integral promotions are being done.

Jeff Barr

unread,
Dec 21, 1988, 4:47:12 PM12/21/88
to
In article <8...@quintus.UUCP>, o...@quintus.uucp (Richard A. O'Keefe) writes:
> he...@utzoo.uucp (Henry Spencer) writes:
> >- 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 recently had a very similar problem. A *superb* "name" for that 2 is
> sizeof "/"

(*superb*)? Personally, I don't see any connection. I'd rather use

(sizeof (""))

to indicate the overhead (if you will) to store a string.

Jeff
--
/-------------------------------------------------------\
/ Jeff Barr AMS-DSG uunet!amsdsg!jeff 800-832-8668 \
\ American Express: "Don't leave $HOME without it". /
\-------------------------------------------------------/

Tom Stockfisch

unread,
Dec 21, 1988, 6:25:16 PM12/21/88
to
In article <1988Dec15....@utzoo.uucp> he...@utzoo.uucp (Henry Spencer) writes:
> 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?

In this case I usually write

foo = malloc( strlen(a) + strlen(b) + sizeof("/") );

What do you think of that?

--

|| Tom Stockfisch, UCSD Chemistry t...@chem.ucsd.edu

Liber

unread,
Dec 21, 1988, 7:38:10 PM12/21/88
to
In article <11...@goofy.megatest.UUCP> djo...@megatest.UUCP (Dave Jones) writes:
>From article <26...@m2-net.UUCP>, by rem...@m-net.UUCP (John H. Remmers):

>> #define Catspace(s,t) (strlen(s) + strlen(t) + 1)

>You are a candidate for SLMA (Silly Little Macros Anonymous). [:-)]

>But if you don't like the naked "1", how about this?

>foo = malloc( strlen(s) + strlen(t) + sizeof('\0'));

>Tells it all. And keeps the reader on track, not grepping around
>for macros.

It also happens to be WRONG! (Actually, if you are only using it for
malloc(), it will work; you just end up allocating more space than is
actually needed.) Quoting from dpANS C 10/88 draft, section 3.1.3.4
(character constants), subsection on semantics (p 30):

"An integer character constant has type int."

This means, among other things, that sizeof('\0') == sizeof(int), and
not sizeof(char).
--
NEVIN ":-)" LIBER AT&T Bell Laboratories nev...@ihlpb.ATT.COM (312) 979-4751

T. William Wells

unread,
Dec 21, 1988, 8:46:35 PM12/21/88
to
In article <24...@ficc.uu.net> pe...@ficc.uu.net (Peter da Silva) writes:
: In article <3049@arcturus>, ev...@arcturus.UUCP (Wade Guthrie) writes:

: > 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);
: > > }
:
: This is a wonderful and clean extension to 'C' that solves the loop problem
: once and for all!

This is a bad syntax.

Why?

Because of this:

do
statement
while (expr);
statement

See the difference? Well, in case you didn't, it is the semicolon at
the end of the while expression. This is damned hard to spot and does
not lead to a syntax error.

I'll stick to using a break.

T. William Wells

unread,
Dec 21, 1988, 9:18:48 PM12/21/88
to
In article <11...@goofy.megatest.UUCP> djo...@megatest.UUCP (Dave Jones) writes:
: But if you don't like the naked "1", how about this?

:
: foo = malloc( strlen(s) + strlen(t) + sizeof('\0'));
:
: Tells it all. And keeps the reader on track, not grepping around
: for macros.

How about sizeof('\0') is equal to the size of an integer, which is
unlikely to be 1?

Remember, in C, character constants are integer constants.

Sean Fagan

unread,
Dec 21, 1988, 9:30:58 PM12/21/88
to
In article <17...@buengc.BU.EDU> b...@buengc.bu.edu (Blair P. Houghton) writes:
>In article <8...@calvin.EE.CORNELL.EDU> jo...@calvin.ee.cornell.edu.UUCP (John Sahr) writes:
>>>In article <85...@alice.UUCP>, a...@alice.UUCP (Andrew Koenig) writes:
>But what's wrong with [the following code]?
] do {

] process(ch);
] process2(ch);
] process3(ch);
] } while (
] ch = getchar(),
] ch &= MASK,
] ch = table_look_up[ch],
] report_status(ch),
] ch != EOF
] );

Uhm, little thinks like the fact that quite a few compilers will generate
the equivalent of:
do {
proces(ch);
process2(ch);
process3(ch);
} while (
getchar(), ch&MASK, table_look_op[ch], report_status(ch),
ch != EOF)
;

which is all that you're guarenteed (assuming the compiler does no
optimizations). Put some optimizations in (assuming ch is non-volatile in
a dpANSI compiler, or the compiler assumes it isn't), and you get:

getchar(), report_status(ch), ch!=EOF

as the conditional for the while.

Also, ch is not initialized to the getchar(), which it was in the initial
example (which I deleted, of course), and the code looks horrible.

Is that enough?

--
Sean Eric Fagan | "Merry Christmas, drive carefully and have some great sex."
se...@sco.UUCP | -- Art Hoppe
(408) 458-1422 | Any opinions expressed are my own, not my employers'.

Stuart Gathman

unread,
Dec 21, 1988, 9:46:03 PM12/21/88
to
In article <85...@alice.UUCP>, a...@alice.UUCP (Andrew Koenig) writes:

> int i, status, count = 0;
> char temp[THINGSIZE];
> do {
> readthing(precious);
> ++count;
> for (i = 0; i < THINGSIZE; i++)
> temp[i] = precious[i];
> status = munge(temp);
> } while (status) {
> for (i = 0; i < THINGSIZE; i++) {
> if (temp[i] != precious[i])
> printf ("munge changed element %d of line %d\n",
> i, count);
> }
> }

This is a necessary contruct. In a structured assembler language I developed,
it goes like this:

LOOP REPEAT
statements statements
WHILE WHEN or UNTIL WHEN
statements statements
THEN cond THEN cond

The WHILE part was executed first. *Any* condition could contain
a 'WHEN' clause. (As in 'IF (A,LT,B),OR,WHEN . . .')

A generalized WHEN construct would be welcome in 'C'. The specific
case being discussed, however, is handled quite well
by the break statement in standard 'C'!

for (;;) {
c = getchar();
if (c == EOF) break;
process(c);
}
--
Stuart D. Gathman <stu...@bms-at.uucp>
<..!{vrdxhq|daitc}!bms-at!stuart>

Stuart Gathman

unread,
Dec 21, 1988, 9:53:46 PM12/21/88
to
In article <26...@m2-net.UUCP>, rem...@m-net.UUCP (John H. Remmers) writes:

> The space requirement for a string concatenation is a frequently-needed
> value; it's worth having a macro to represent it:

> #define Catspace(s,t) (strlen(s) + strlen(t) + 1)

> In terms of this, the malloc() call can be written:

> foo = malloc(Catspace(s,t) + sizeof('/'));

> thus making it explicit that you're concatenating two strings and
> allocating one more byte for an extra character. Readability is
> improved, and the question of naming the "2" never comes up.

Of course, this is incorrect since sizeof('/') is 2 or 4 depending on
your machine. But the concept is good . . .

Dave Caswell

unread,
Dec 22, 1988, 3:05:38 AM12/22/88
to
John H. Remmers writes

> The space requirement for a string concatenation is a frequently-needed
> value; it's worth having a macro to represent it:
>
> #define Catspace(s,t) (strlen(s) + strlen(t) + 1)


and Dave Jones rambles
.
.foo = malloc( strlen(s) + strlen(t) + sizeof('\0'));
|
|--this is four on 32-bit machines

.Tells it all. And keeps the reader on track, not grepping around
.for macros.

An advantage of functions or macros is what you write it once and debug it;
you cut down the chance of errors. I wouldn't mind searching for code what
worked.

--
Dave Caswell (former EMU student)
Greenwich Capital Markets uunet!philabs!gcm!dc

rogerson

unread,
Dec 22, 1988, 10:21:05 AM12/22/88
to

Actor, an OOPS programming language for Microsoft Windows, uses
the following construct for controlling loops:

loop
...
while ( )
...
endloop

To get the normal while-do or do-while it would look like:
loop while ( ) /* while - do */
...
endloop
and
loop /* do - while */
...
while ( )
endloop

This is much more readable then the proposed C version, but then
it would be incompatible with current C.

A simple solution to the problem is to use a for statement and
a break statement. This is like Modula II which has the
LOOP-EXIT-END control statement.

-----Dale
Rogerson-----

Fred Fish

unread,
Dec 22, 1988, 12:24:16 PM12/22/88
to
In article <2...@twwells.uucp> bi...@twwells.UUCP (T. William Wells) writes:
<: < In article <85...@alice.UUCP<, a...@alice.UUCP (Andrew Koenig) writes:
<: < < do {
<: < < ch = getchar();
<: < < } while (ch != EOF) {
<: < < process(ch);
<: < < }
<
< do
< statement
< while (expr);
< statement
<
<See the difference? Well, in case you didn't, it is the semicolon at
<the end of the while expression. This is damned hard to spot and does
<not lead to a syntax error.

Since this is my pet peeve #1 about C style, I couldn't resist. There
is no ambiguity if you simply make it a habit to ALWAYS include braces
for {if, while, do, for} etc, even when they are not strictly necessary.

I was recently helping out a freshman CS major with her C homework and
found out, to my horror, that the teacher in the course was marking
off points for code which included braces when they weren't strictly
required. They were teaching her to write code like:

inchar = getchar ();
while (inchar != EOF)
if (inchar == 0)
goto done;
else
inchar = getchar ();
done: return inchar;

Ickkk!!!
-Fred
--
# Fred Fish, 1346 West 10th Place, Tempe, AZ 85281, USA
# asuvax!nud!fishpond!estinc!fnf (602) 921-1113

Blair P. Houghton

unread,
Dec 22, 1988, 12:24:21 PM12/22/88
to
In article <1963@scolex> se...@sco.COM (Sean Fagan) writes:
>In article <17...@buengc.BU.EDU> b...@buengc.bu.edu (Blair P. Houghton) writes:
[in response to:]

>>>>In article <85...@alice.UUCP>, a...@alice.UUCP (Andrew Koenig) writes:
>>But what's wrong with [the following code]?
>> do {
>> process(ch);
>> process2(ch);
>> process3(ch);
>> } while (
>> ch = getchar(),
>> ch &= MASK,
>> ch = table_look_up[ch],
>> report_status(ch),
>> ch != EOF
>> );
>
>Uhm, little thinks like the fact that quite a few compilers will generate
>the equivalent of:

[...broken code deleted...]
Buy yerself a new compiler. This one's screwed.

[...optimization of broken code deleted quickly...]


>Also, ch is not initialized to the getchar(), which it was in the initial
>example (which I deleted, of course), and the code looks horrible.

I happen to think it looks just fine; the usage of "(" and ");" parallels
the usage of "{" and "}", and the comma is akin to a sort of sub-semicolon.
(Will the Semanticists please put away those rotten vegetables? Thank you.)

It Just Ain't C.

>Is that enough?

No, you forgot to impugn my ancestry.

And to mention that statement is not expression, expression is not
statement. The example above is not complete by any means, and will
break if I try to put a "for(expr;expr;expr);," in the middle of the
while-block.

--Blair
"...something about..."

Rahul Dhesi

unread,
Dec 22, 1988, 1:22:00 PM12/22/88
to
If we're really redesigning the language, a single general construct
suffices:

do
... /* zero or more statements */
while condition
... /* zero or more statements */
done
--
Rahul Dhesi UUCP: <backbones>!{iuvax,pur-ee}!bsu-cs!dhesi

Ken Arromdee

unread,
Dec 22, 1988, 2:51:50 PM12/22/88
to
>How about sizeof('\0') is equal to the size of an integer, which is
>unlikely to be 1?
>Remember, in C, character constants are integer constants.

I was under the impression that "sizeof" is done at compile time and isn't
really a function, so this would correctly return 1.
--
"Thinking small is seeing your bus on the other side of the street, and
wishing you could teleport across to catch it."

--Kenneth Arromdee (ins_...@jhunix.UUCP, arro...@crabcake.cs.jhu.edu,
g49i...@jhuvm.BITNET) (not arrom@aplcen, which is my class account)

William C. DenBesten

unread,
Dec 22, 1988, 3:05:25 PM12/22/88
to
How 'bout something simple that works _now_?

#define loop for(;;)
#define exitif(a) if (a) break

main()
{
char ch;
loop {
ch = getchar();
exitif (ch==EOF);
putc(ch);
}
}

This seems much less prone to a missing semi-colon causing a really nasty
error. IMHO, this is much easier to follow than do{}while(){};.

--
William C. DenBesten | denb...@bgsu.edu
Dept of Computer Science | CSNET denbeste%andy.b...@relay.cs.net
Bowling Green State University | UUCP ...!osu-cis!bgsuvax!denbeste
Bowling Green, OH 43403-0214 |

Vincent C. Hatem

unread,
Dec 22, 1988, 3:30:39 PM12/22/88
to
In article <1988Dec21.1...@ateng.ateng.com>, ch...@ateng.ateng.com (Chip Salzenberg) writes:
] According to he...@utzoo.uucp (Henry Spencer):

Right, chip.

Last I heard sizeof("/") == sizeof(char *) - which is almost never 2, and
NEVER portable.

How about the more accurate:
foo = malloc(strlen(a)+strlen(b)+(2*sizeof(char)));

--
Vincent C. Hatem | att ---->\ (available from any
AT&T International | ulysses ->\ Action Central site)
International Operations Technical Support | bellcore ->\___ !attibr!vch
1200 Mt Kemble Ave, Basking Ridge, NJ 07920 | (201) 953-8030

Chris Torek

unread,
Dec 22, 1988, 4:42:50 PM12/22/88
to
>>sizeof('\0') is equal to the size of an integer ....

>>Remember, in C, character constants are integer constants.

In article <4...@aplcen.apl.jhu.edu> ar...@aplcen.apl.jhu.edu


(Ken Arromdee) writes:
>I was under the impression that "sizeof" is done at compile time and isn't
>really a function, so this would correctly return 1.

sizeof is indeed not a function, yet sizeof('\0') is the same as
sizeof(0) and sizeof(int), which are usually not the same as sizeof(char).
The second `>>' line above is the key: the type of '\0' is int, not char.
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain: ch...@mimsy.umd.edu Path: uunet!mimsy!chris

Dave Jones

unread,
Dec 22, 1988, 6:46:12 PM12/22/88
to
From article <17...@dataio.Data-IO.COM>, by bri...@Data-IO.COM (Walter Bright):


Gack! You are correct. Due to certain intermittent reduced neurological
function (sometimes I can be real dumb), it is hard for me to remember
that in C, "character" constants are of type int, not char. Seems goofy
to me. Can anyone suggest a rationale, so that I can remember this arcane
fact?

Okay. You get bucked off, you climb right back in the saddle, right?


How about,


foo = malloc( strlen(s) + strlen(t) + sizeof((char)'\0'));

Russ Nelson

unread,
Dec 22, 1988, 10:42:17 PM12/22/88
to
In article <220.n...@orcenl.uucp> ben...@orcenl.uucp (Bjorn Engsig) writes:

I've used the n-key very much lately :-(

I promise I will never mention indentation again.
I promise I will never mention indentation again.
I promise I will never mention indentation again.
I promise I will never mention indentation again.
(this is *all* in response to my quest for indentation standards)
I promise I will never mention indentation again.
I promise I will never mention indentation again.
I promise I will never mention indentation again.
I promise I will never mention indentation again.
....
--
--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.

Dave Jones

unread,
Dec 23, 1988, 12:27:01 AM12/23/88
to
From article <7...@attibr.UUCP>, by v...@attibr.UUCP (Vincent C. Hatem):

>
> Last I heard sizeof("/") == sizeof(char *) - which is almost never 2, and
> NEVER portable.
>

First I heard sizeof("/") == 2 which is sometimes sizeof(char*), and
ALWAYS portable.

On my machine, a 68020 based Sun3/60, sizeof(char*) seems to be either
four or seven, depending.

Don't feel bad. I blew sizeof('\0') bigtime.


% cat foo.c
main()
{
printf("%d %d\n", sizeof(char*), sizeof ("foobar"));
exit(0);
}
% cc foo.c
% a.out
4 7

John F Carr

unread,
Dec 23, 1988, 3:04:00 AM12/23/88
to
In article <2...@twwells.uucp> bi...@twwells.UUCP (T. William Wells) writes:
>This is a bad syntax.
> do
> statement
> while (expr);
> statement
>
>See the difference? Well, in case you didn't, it is the semicolon at
>the end of the while expression. This is damned hard to spot and does
>not lead to a syntax error.

Do you never use loops in C? If you do, you are vulnerable to the same
mistake regardless of which variety you use.

while(expr);
statement

and

for(;;);

are legal under the current C standard. I do not see how the proposed
extension creates any new potential for failure.

--
John Carr "When they turn the pages of history,
j...@Athena.mit.edu When these days have passed long ago,
bloom-beacon! Will they read of us with sadness
athena.mit.edu!jfc For the seeds that we let grow?" --Neil Peart

Guy Harris

unread,
Dec 23, 1988, 3:53:46 AM12/23/88
to
>Last I heard sizeof("/") == sizeof(char *)

I don't know who you heard that from, but I suggest you take anything
else they have to say about C with a grain of salt; it is not true. "/"
is an array of "char" with two elements, not a pointer to "char". In
some contexts, that "array of 'char'" expression gets converted to a
"pointer to 'char'" that points to the array's first member; however,
"argument of the 'sizeof' operator" is not one of those contexts.

T. William Wells

unread,
Dec 23, 1988, 5:53:00 AM12/23/88
to
In article <4...@aplcen.apl.jhu.edu> ar...@aplcen.UUCP (Ken Arromdee (600.429)) writes:
: >How about sizeof('\0') is equal to the size of an integer, which is

: >unlikely to be 1?
: >Remember, in C, character constants are integer constants.
:
: I was under the impression that "sizeof" is done at compile time and isn't
: really a function, so this would correctly return 1.

Well, you are right that sizeof is done at compile time, and it isn't
a function. But it won't return 1.

Sizeof is an operator. The thing it is operating on is a character
constant. In C, a character constant *is* an integer. Thus sizeof a
character constant must the the same as the sizeof an integer. (Now,
for the gurus: am I right in saying integer, or should I say `of some
integral type'?)

T. William Wells

unread,
Dec 23, 1988, 6:06:17 AM12/23/88
to
In article <8...@estinc.UUCP> f...@estinc.UUCP (Fred Fish) writes:
: Since this is my pet peeve #1 about C style, I couldn't resist. There

: is no ambiguity if you simply make it a habit to ALWAYS include braces
: for {if, while, do, for} etc, even when they are not strictly necessary.

Absolutely. One should always include optional braces. There are two
advantages:

1) A decrease in the likelyhood of programming errors.

2) An increase in the readability of the program.

One should also never write a compound statement on the same line as
the head of the statement it is embedded in. E.g., instead of:

for (a; b; c) statement;

one should write:

for (a; b; c) {
statement;
}

Doing that makes finding the statement quite a bit easier.

: I was recently helping out a freshman CS major with her C homework and


: found out, to my horror, that the teacher in the course was marking
: off points for code which included braces when they weren't strictly
: required. They were teaching her to write code like:
:
: inchar = getchar ();
: while (inchar != EOF)
: if (inchar == 0)
: goto done;
: else
: inchar = getchar ();
: done: return inchar;
:
: Ickkk!!!

Double Ickkkk!!!! A goto where a break would have done.

Jonathan Bayer

unread,
Dec 23, 1988, 10:25:23 AM12/23/88
to
In article <24...@ssc-vax.UUCP>, d...@ssc-vax.UUCP (David Geary) writes:
> In article <65...@polyslo.CalPoly.EDU>, cqu...@polyslo.CalPoly.EDU (Chris (i = --i++;) Quenelle) writes:

> 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.
>


You must have some either very lazy or very stupid Pascal programmers in
your class (no reflection on you). I too am a reformed Pascal
programmer. As a matter of fact, I still program in Pascal. I also
program in C. It would drive me bonkers if I had to look at my own C
code which had Pascal constructs in it. It is bad enough that I still
get the two languages mixed up occasionally (especially when I am
working on a project which has both Pascal code and C code in it). I
can not understand those programmers who try to fit one language into
another. The difference between languages is what makes a language
different. Changing a language to make it seem a bit more like an
already-known language is akin to buying a Fererri and putting a VW
engine in it because you know how to work on the VW engine.


Jonathan Bayer
Intelligent Software Products, Inc.

--
life used to be so simple.

John H. Remmers

unread,
Dec 23, 1988, 12:04:37 PM12/23/88
to
In article <11...@goofy.megatest.UUCP> djo...@megatest.UUCP (Dave Jones) writes:
>From article <26...@m2-net.UUCP>, by rem...@m-net.UUCP (John H. Remmers):
>...

>> The space requirement for a string concatenation is a frequently-needed
>> value; it's worth having a macro to represent it:
>>
>> #define Catspace(s,t) (strlen(s) + strlen(t) + 1)
>>
>
>You are a candidate for SLMA (Silly Little Macros Anonymous).
>
The merits are debatable, I suppose, but if an application requires a
lot of dynamic allocation of space for strings, hiding the 1 for the
null byte in a macro definition is a way to defend against forgetting
it (a common error, in my experience). The wisdom of this approach
ultimately is determined by frequency of use. Agreed, inventing
macros for isolated situations is not good practice. What I was trying
to say, perhaps not too clearly, is that a macro for string concatena-
tion space might find sufficient use to be worth defining, and that
*if* that is the case, this is a natural place to use it.

>
>But if you don't like the naked "1", how about this?
>
>foo = malloc( strlen(s) + strlen(t) + sizeof('\0'));
>
As a couple of people pointed out to me in mail, '\0' and '/' are
ints, so sizeof('\0') = sizeof(int), usually 2 or 4, and more space
is allocated than needed.

It was not the naked "1" I was questioning so much as the naked "2".

John H. Remmers

unread,
Dec 23, 1988, 12:28:26 PM12/23/88
to
In article <11...@goofy.megatest.UUCP> djo...@megatest.UUCP (Dave Jones) writes:
>From article <26...@m2-net.UUCP>, by rem...@m-net.UUCP (John H. Remmers):
>...
>> The space requirement for a string concatenation is a frequently-needed
>> value; it's worth having a macro to represent it:
>>
>> #define Catspace(s,t) (strlen(s) + strlen(t) + 1)
>>
>
>You are a candidate for SLMA (Silly Little Macros Anonymous).

Well, maybe, maybe not. Hiding the 1 for the null byte in a macro
definition is a defense against forgetting it. Promiscuous ad hoc
invention of macro names is of course Bad Programming Practice;
what I was trying to say, perhaps not too clearly, is that *if* dynamic
allocation of space for strings is a frequently-needed operation in
an application, *then* a macro (or maybe a set of macros) might be
worthwhile, and that the example at hand is a natural place to use it.

>But if you don't like the naked "1", how about this?
>
>foo = malloc( strlen(s) + strlen(t) + sizeof('\0'));

A couple of people have pointed out to me in mail that
sizeof(<character-constant>) is wrong, since a character-constant is
an int. Hence sizeof('\0') = sizeof(int), usually 2 or 4, and more
space is allocated than needed. Actually, I don't mind the naked
"1"; it was the naked "2" I was questioning.


--
John H. Remmers | ...umix!m-net!remmers
Dept. of Computer Science |---------------------------------------------
Eastern Michigan University | My opinions and those of my employer are the
Ypsilanti, MI 48197 | same, but my employer doesn't know that yet.

Chris Calabrese[mav]

unread,
Dec 23, 1988, 12:58:47 PM12/23/88
to
In article <2...@twwells.uucp>, bi...@twwells.uucp (T. William Wells) writes:
> In article <8...@estinc.UUCP> f...@estinc.UUCP (Fred Fish) writes:
> ...

> : I was recently helping out a freshman CS major with her C homework and
> : found out, to my horror, that the teacher in the course was marking
> : off points for code which included braces when they weren't strictly
> : required. They were teaching her to write code like:
> :
> : inchar = getchar ();
> : while (inchar != EOF)
> : if (inchar == 0)
> : goto done;
> : else
> : inchar = getchar ();
> : done: return inchar;
> :
> : Ickkk!!!
>
> Double Ickkkk!!!! A goto where a break would have done.

This is yet another tripple icky example of CS professors
thinking that just because they can get the example programs
in K&R to compile, and because they did work in Fortran in
their thesis on astrophysics, they are qualified to teach
C (or any other language). Wrong, wrong, wrong.

Any C guru qualified (in my humble opinion) to teach
C would be trying to teach code which looks like:

/*
* assume students have not learned the ',' operator yet
*/
do {
inchar = getchar();
} while(inchar != EOF && inchar);
return inchar;

Personally, I haven't decided whether the while should be lined
with the do or the loop body yet, but I like the brace alignment
this way.
--
Christopher J. Calabrese
AT&T Bell Laboratories
att!ulysses!cjc c...@ulysses.att.com

Peter da Silva

unread,
Dec 24, 1988, 7:47:54 PM12/24/88
to
In article <11...@ulysses.homer.nj.att.com>, c...@ulysses.homer.nj.att.com (Chris Calabrese[mav]) writes:
> /*
> * assume students have not learned the ',' operator yet
> */
> do {
> inchar = getchar();
> } while(inchar != EOF && inchar);
> return inchar;

I would recommend in this instance to make the test experession:

inchar != EOF && inchar != '\0'

Since inchar is obviously not a boolean (it has three distinct possible
values: EOF, 0, and anything else).
--
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.
Work: uunet.uu.net!ficc!peter, pe...@ficc.uu.net, +1 713 274 5180. `-_-'
Home: bigtex!texbell!sugar!peter, pe...@sugar.uu.net. 'U`
Opinions may not represent the policies of FICC or the Xenix Support group.

Chris Siebenmann

unread,
Dec 26, 1988, 2:17:54 AM12/26/88
to
In article <26...@m2-net.UUCP> rem...@m-net.UUCP (John H. Remmers) writes:
...
>The space requirement for a string concatenation is a frequently-needed
>value; it's worth having a macro to represent it:
> #define Catspace(s,t) (strlen(s) + strlen(t) + 1)
>In terms of this, the malloc() call can be written:
> foo = malloc(Catspace(s,t) + sizeof('/'));

For true safety, I'd write this as

foo = malloc(Catspace(s,t)*sizeof(char) + sizeof('/'));

(or redefine Catspace() to do this itself, depending on whether it
returns a character or byte count), just in case someone produces a
compiler where characters aren't single bytes.

[Corrections gratefully accepted; I don't think ANSI mandated
sizeof(char) being one, although a lot of code will probably break if
it isn't.]
[Route uucp mail manually until the January uucp maps come out; a
machine on the favorite route to the Ziebmef just went away.]
--
"...in all the history of Earth, there's never been a heaven, never
been a house of gods that was not built on human bones."
Chris Siebenmann uunet!{utgpu!moore,attcan!telly}!ziebmef!cks
c...@ziebmef.UUCP or .....!utgpu!{,ontmoh!,ncrcan!brambo!}cks

Mark A Terribile

unread,
Dec 26, 1988, 10:23:32 PM12/26/88
to
: : ... helping out a freshman CS major with her C homework [I] found out ...
: : that the teacher ... was marking off points for code which [used] braces
: : when they weren't strictly required. They were teaching her to write ...:
: :
: : inchar = getchar ();

: : while (inchar != EOF)
: : if (inchar == 0)
: : goto done;
: : else
: : inchar = getchar ();
: : done: return inchar;
: :
: : Ickkk!!!
: Double Ickkkk!!!! A goto where a break would have done.

Let's see how many violations of good form we can see.

There's the use of a goto, period.
There's the use of a goto where a break would serve.
There's the use of an else after a goto or break. (Some would praise this.
I don't. See the example on p. 45 of Kernighan and Plaugher, *The
Elements of Programming Style*, featuring the label ``NEXT_C'' .
It's a splendid example of dead-spot-in-code-before-else.)
There's the use of a goto to break multiple levels of structure without
closing braces to remind the reader how many levels are being broken.
There are two seperate calls to getchar() at opposite ends of the loop, one
for the first pass, and one for all subsequent passes.
There are two adjacent levels of control structure, both omitting braces. This
is not only a readability disaster, but a maintainance nightmare.
There's the use of a goto and label to fold surruptitiously two exits from the
loop into one. It's really tough to see at a glance both the goto-exit
and the loop's natural exit-from-the-top.
There's the use of a `` goto X; ... X: return y; '' If the purpose of the
loop is to return a value at a certain point, then the return ought to
be right in the loop, with the bottom exit return a special case.
There's the treatment of two effectively symmetrical cases in vastly different
ways--return on EOF by the loop's control clause, and return on value
zero by a goto, and what is worse, a goto that purports (by it's
placement in the if-else) to be coordinate (rather than subordinate or
superior) to the loop-continuation operation.

Whew! That's enough for the moment. I'd deem it a favor to future generations
of programmers and to the industry as a whole if someone would collect the
responses from the net and mail them to the wall-eyed buzzard, and to that
buzzard's superiors. And I'll bet a very nice dinner that I've written more
code for which customers ultimately paid real dollars than he has.
--

(This man's opinions are his own.)
From mole-end Mark Terribile

Doug Gwyn

unread,
Dec 26, 1988, 11:55:02 PM12/26/88
to
In article <17...@dataio.Data-IO.COM> bri...@dataio.Data-IO.COM (Walter Bright) writes:
>But doesn't sizeof('\0') return sizeof(int), instead of sizeof(char)?

Yes ...

>Remember, the integral promotions are being done.

... but integral promotion has nothing to do with it. '\0' IS an integer
constant of value 0 and type int, not char.

Doug Gwyn

unread,
Dec 27, 1988, 12:14:42 AM12/27/88
to
In article <33...@bgsuvax.UUCP> denb...@bgsuvax.UUCP (William C. DenBesten) writes:
>#define exitif(a) if (a) break

Doesn't work (exercise for the student).
Also, recall the earlier discussion about Bourne's Algolish C macros.

Doug Gwyn

unread,
Dec 27, 1988, 12:17:41 AM12/27/88
to
In article <15...@mimsy.UUCP> ch...@mimsy.UUCP (Chris Torek) writes:
>sizeof is indeed not a function, yet sizeof('\0') is the same as
>sizeof(0) and sizeof(int), which are usually not the same as sizeof(char).

We should probably explain also that it's the same as sizeof 0 and
sizeof '\0', but not sizeof int (which is illegal). Since any C
text should explain this, look it up if you don't understand.

It is loading more messages.
0 new messages