One more point regarding = and == (more flamage)

Stephen Carlson scc at rlgvax.Reston.ICL.COM
Wed Mar 27 04:03:11 AEST 1991


In article <925 at isgtec.UUCP> robert at isgtec.UUCP writes:
>In article <355 at smds.UUCP>, rh at smds.UUCP (Richard Harter) writes:
>|> Re:
>|>  a) while (*foo++ = *bar++)
>|>  b) while (*foo ++ == *bar++)
>|>  c) while ((*foo++ = *bar++) != 0)
>|> 
>|> Sundry claims have been made that (c) is "good style" versus (a).  The
>|> original objection was couched in terms of "testing on assignment inside
>|> conditionals is bad form".  IMNSHO most of the arguments and dogmatic
>|> statements are so much rubbish.
>Well the biggest argument has been if you use a) the maintainer can't tell
>if you meant a) or b);  if you use c) the maintainer KNOWS you meant a).
>This isn't rubbish.

The statement:

	while (*s++ = *t++)
		;

is a standard C idiom to copy two zero-terminated arrays [K&R gives this as
an example implementation of strcpy()].  Any programmer that does not
immediately understand this cannot be called a C programmer.  The other
statement:

	while (*s++ == *t++)
		;

is not well set up to compare two arrays.  It does not check for a zero
termination.  It is really only useful when the programmer has already
set up guaranteed unequal sentinals at the end of the array.  Then the
pointers after the loop are one greater than would be useful.

The point is, for these kinds of statements, statement (a) is normal, common,
and useful.  Statement (b) is suspicious, rare, and useless.

>|> (c) is no more or no less clean than (a).
>It's just more readable.

Statement (c) tries to make explicit that the assignment in a conditional is
no accident, while the real case--for this kind of expressions--is that the
equality is likely to be wrong.

Since statement (b) is much more out of the ordinary, I would prefer some
marking such as a comment or a different but equivalent coding to assert
that it is really indended.  The explicit marking is statement (c)'s case
does just the opposite--it brings attention to the more common and more often
correct construct.

>|> In both cases you are testing
>|> the value of the contents, not of foo, but of foo before it was incremented.
>|> Does either statement say that?  Not obviously -- you have to understand C,
>|> get down in the muck with it, before it is is obvious.
>The 'C' is obvious in all of a), b) and c); the programmers INTENT is only
>obvious in b) and c)!

Here, I disagree.  The programmers intent is obvious in (a), unclear in (b),
just annoying in (c).  Any one who does immediately understand (a) is not a
C programmer.

As far as the general issues of assignments in conditional contexts is
concerned, it is important to look that the situations they happen in:

(1) Zero-terminated array copies:

	while (*s++ = *t++)
		;

The assignment is preferred because it a common C idiom, and it alternative
is rare.  If the alternative is really preferred, the loop should be recoded:

	while (*s == *t)
		s++, t++;
	s++, t++;

Of course, as far as utility is concerned, the second double increment is
not usually wanted (but that makes it equivalent to the alternative).

(2) Set and test a function's return value.

	if (ret = function()) ...

Being that function calls are expensive and generally cannot be redone, this
form is OK for concise code, especially as a second condition as in

	if (flag && (ret = function())) ...

Of course, one could always code:
	
	ret = function();
	if (ret) ...

As far as the alternative is concerned, being somewhat rarer I would prefer
to have its intent clearly marked as in:

	if (function() == value)

A missing '=' here is a compile time error.

(3) All other cases.

Since the test for equality is much more prevalent in all other case, the
onus is on the assignment case to make that intent clear.  There are several
styles:

	if ((a = b) != 0) ...

	a = b;
	if (a) ...

	if (!!(a = b)) ...

	if ((a = b)) ...

All are equivalent; all work; all indicate the intent.  Try to be consistent
though.  Inconsistency should have a purpose.

A good style should not blind but take into account to usefulness and
frequency of the construct.

-- 
Stephen Carlson           | ICL OFFICEPOWER Center    | In theory, theory and
scc at rlgvax.reston.icl.com | 11490 Commerce Park Drive | practice are the same.
..!uunet!rlgvax!scc       | Reston, VA  22091         |



More information about the Comp.lang.c mailing list