Path: utzoo!utgpu!news-server.csri.toronto.edu!clyde.concordia.ca!uunet!mstan!amull From: amull@Morgan.COM (Andrew P. Mullhaupt) Newsgroups: comp.lang.c Subject: Re: why bother with operator precedence Message-ID: <798@s6.Morgan.COM> Date: 27 Mar 90 14:50:21 GMT References: <2205@osc.COM> <340018@hplvli.HP.COM> <19356@megaron.cs.arizona.edu> <894@dino.cs.iastate.edu> <2677@sunquest.UUCP> <12845@csli.Stanford.EDU> Reply-To: amull@Morgan.COM (Andrew P. Mullhaupt) Organization: Morgan Stanley and Co., NY, NY Lines: 80 I agree: there is no good reason to learn very much of the C precedence table, and there are some good reasons not to. If you have to program in more than one language on a daily basis, you just end up getting annoyed at the idiomatic differences in expression evaluation, and you end up skipping niceties like "do I need parentheses to separate boolean clauses in a conditional?" and putting in parentheses because they are universal. This might be coding for some kind of lowest common denominator but anything else is exposed to some kind of risk. When you find someone else's code which relies on precedence to compress many operations into one, you can pull apart the run-on expression and form simple statements. Note: use of the 'short-circuit' booleans and side-effects should be pulled apart into conditionals, or at least formatted to reflect the flow of control. If you want to express a multiple branch conditional you expect something like: if (C1) { S1; } else if (C2) { /* separation of lines is used */ S2; /* to indicate flow of control */ if (C3) { S3; } } else { S4; } but when you have an assignment to a variable, you usually expect something like: V = Expression; /* on one line if possible */ so when the two are combined (as some programmers often do in C) what should the reader legitimately expect? You don't often see result = E1 || (fail_1_act, E2) || (fail_2_act, E3); indented as: result = E1 || (fail_1_act, E2) || (fail_2_act, E3); so unless you're out for the last drop of optimization you should use: if (E1) { /* space is now available for */ result = TRUE; /* useful documentation */ } else { fail_1_act; if (E2) { /* for each branch */ result = TRUE; } else { fail_2_act; result = E3; } } and hope that your compiler knows enough to find common subexpressions across the conditional statements. In the short-circuit boolean version, fail_1_act and fail_2_act are likely to be evaluated for side effects. (What else is the role of the comma operator?) Suppose that fail_1_act affects the value of the expression E3. The effect of this action is more clearly expressed in the last version. Some might be tempted to use "if (result=E1) ..." but there are some unnecessary risks in this form. Replacing the "result = TRUE" statements might convey an impression that code has been left out. I think this example points out how reliance on side effects and use of precedence in the C language (which are common practices) lead to unnecessary puzzles in reading C source. Some C programmers may know enough to correctly practice minimal parenthesis code, but some other programmers know enough not to bother with high-risk, low-reward code. Later, Andrew Mullhaupt