[net.lang.c] C programming style poll

philipl@azure.UUCP (Philip Lantz) (04/27/84)

From a style point of view, I personally prefer

	y = (x == 5);

WITH the parentheses, but NOT without them.  I think Boolean expressions
are as valid a part of the C language as they are of Pascal, even though
there is no specific declaration for Boolean variables.

However, since I have a compulsion to write the tightest code possible,
I use
	y = 0;
	if (x == 5)
	    y = 1;
What's that?  Yes, on every C compiler I've checked (pcc and Ritchie
and others) the version with the "if" generates BETTER code than
either of the other two forms.  (The other two forms generate identical
code.)

By the way, I agree that the first form above may not be guaranteed to
be entirely equivalent to the others, but if y is assigned to a Boolean
expression, it should be tested with
	if (y)
	if (!y)
or possibly
	if (y == 0)
	if (y != 0)
but never with
	if (y == 1)
	if (y != 1)
The first four forms generate better code (no compare instruction on most
machines), but especially do not depend on the value of a Boolean being 1
when true.

Philip Lantz
Tektronix, Inc.
tektronix!tekmdp!philipl

dwr@ccieng6.UUCP ( Donald Wallace Rouse II) (05/02/84)

xxxxxxxxxxxxxxxxxxxxxxxx
>
>	(1)		y = (x == 5);
>
>
>	(2)		y = 0;
>			if (x == 5)
>				y = 1;
>
> By the way, I agree that the first form above may not be
> guaranteed to be entirely equivalent to the others, but if y is
> assigned to a Boolean expression, it should be tested with
>
>	if (y)
>	if (!y)
> or possibly
>	if (y == 0)
>	if (y != 0)
> but never with
>	if (y == 1)
>	if (y != 1)

According to the K&R bible, p. 41 at the top:

	Another useful form of type conversion is that
	relational expressions like i > j and logical
	expressions connected by && and || are defined to have
	value 1 if true, and 0 if false.  Thus the assignment

		isdigit = c >= '0' && c <= '9';

	sets isdigit to 1 if c is a digit and to 0 if not.

Therefore, it IS legal (though bad form, in my opinion)
to use the form "(y == 1)" or "(y != 1)".

I use this definition occasionally to access arrays, as in:

	char *	tf [] = {"false", "true"};
	...
	printf ("The supposition that x is 0 is %s\n", tf [x == 0]);

									D2

amigo@iwlc6.UUCP (John Hobson) (05/04/84)

Well, the results of my poll are in, and here they are.  As you
will recall, the authors of the book THE C PROGRAMMING LIBRARY
gave three examples of code all to assign 1 to the variable y if the
value of x was 5, otherwise give y the value of 0.  There were
three code fragments given by the authors, and one more suggested
by me.  They are:

Version 1

y = 0;
if (x == 5)
	y = 1; 

Note:  When I copied this in my original article, I forgot to indent
the third line.  Several people took the authors to task for not
doing so, but it was not their fault, it was mine.

Version 2 (added)

if (x == 5)
	y = 1;
else
	y = 0;
	
Version 3

y = (x == 5) ? 1 : 0;

Version 4

y = x == 5;

First, before we get to the results, an apology.  I stated that on
page 52 of Kernighan and Ritchie, False was given a value of 0 and
True was given a non-zero value.  As several people pointed out, I
should have looked on page 38, where True is stated to have a value
of 1.

Several people split their votes, saying that the formulation used
would depend on exactly what the person was trying to do in a
particular case.  In these cases, I gave each choice 1/2 point.

And now, the envelope:

In fourth place, with 3 points:  Version 1.

In third place, with 14 1/2 points:  Version 2.

In second place, with 26 1/2 points:  Version 4.

In first place, with 29 points:  Version 3.

Several comments must be made. Virtually everyone who voted for
Version 4, y = x == 5; said that it should be written y = (x == 5);
for better readability.  Also, with one exception, all the people
in favour of this choice said specifically that they would use it
only if y was understood to be a Boolean variable.  Several people
wrote comments that said that they assumed y was Boolean, and a
couple of people suggested code along the lines of:

	y = (x == 5) ? TRUE : FALSE;

with TRUE and FALSE defined with appropriate #define statements.

One of the points that the authors made was that y = (x==5)
generates less code.  Well, several people (including I) tried the
several choices, and we all got similar results:

Guy Harris (rlgvax!guy) sent me this:

>>	On our VAX-11, running 4.2BSD (which uses the System III C
>>	compiler and a post-System III optimizer), you get:
>>	
>>	first()
>>	{
>>		register int x, y;
>>	
>>		y = 0;
>>		if(x == 5)
>>			y = 1;
>>	}
>>	
>>	generates
>>	
>>	.globl	_first
>>	.text
>>	_first:	.word	0xc00
>>	clrl	r10
>>	cmpl	r11,$5
>>	jneq	L1
>>	movl	$1,r10
>>	L1:	ret
>>	
>>	second()
>>	{
>>		register int x, y;
>>	
>>		if (x == 5)
>>			y = 1;
>>		else
>>			y = 0;
>>	}
>>	
>>	generates
>>	
>>	.globl	_second
>>	.text
>>	_second:.word	0xc00
>>	cmpl	r11,$5
>>	jneq	L2
>>	movl	$1,r10
>>	jbr	L1
>>	L2:	clrl	r10
>>	L1:	ret
>>	
>>	which is about what you'd expect,
>>	
>>	third()
>>	{
>>		register int x, y;
>>	
>>		y = (x == 5) ? 1 : 0;
>>	}
>>	
>>	generates
>>	
>>	.globl	_third
>>	.text
>>	_third:	.word	0xc00
>>	cmpl	r11,$5
>>	jneq	L2
>>	movl	$1,r0
>>	jbr	L1
>>	L2:	clrl	r0
>>	L1:	movl	r0,r10
>>	ret
>>	
>>	which is *worse* than "second"!  This is because in
>>	"second" it's not evaluating the conditional as an
>>	expression, so it doesn't feel obliged to put the result in
>>	a register; in "third", however, PCC can only figure out
>>	how to do this by evaluating the whole mess "(x == 5) ? 1 :
>>	0" into a register and then moving the register into "y".
>>	
>>	fourth()
>>	{
>>		register int x, y;
>>	
>>		y = x == 5;
>>	}
>>	
>>	generates
>>	
>>	.globl	_fourth
>>	.text
>>	_fourth:.word	0xc00
>>	cmpl	r11,$5
>>	jneq	L2
>>	movl	$1,r0
>>	jbr	L1
>>	L2:	clrl	r0
>>	L1:	movl	r0,r10
>>	ret
>>	
>>	which is *identical* to "third".
>>	
>>	Moral: don't always assume you know better than your
>>	compiler does.

I had similar results using "cc -O" on a PDP 11/70, a VAX 11/780,
and a 3B20 all running under PWB UNIX 5.0.5.  It also works the
same way with a DECUS C compiler (machine unspecified).

My final comment is something that was well put by Clay Phipps:
>>	I am disturbed by the notion that the best code is that 
>>	which reflects the deepest knowledge of a particular language.
>>	This seems to be at odds with the notion of "egoless programming",
>>	because the authors almost seem to be encouraging displays
>>	of knowledge, or in other words, "showing off" by
>>	ego-tripping programmers.  The excerpt indicates that the
>>	authors are indifferent to issues of program clarity and
>>	readability: they can't define or quantify it, so they've
>>	decided that they won't worry about it.  This is
>>	particularly disturbing because of the multitude of facilities 
>>	that C provides for writing clever or opaque code (2nd only
>>	to APL).  I suspect that the authors have never been
>>	required to maintain code written by anyone except themselves.

				John Hobson
				AT&T Bell Labs--Naperville, IL
				ihnp4!iwlc6!amigo