🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.lang.c.moderated
5 messages
5 total messages Started by Bob Calbridge Wed, 27 Mar 1996 00:57
Explaining precedence vs. sequence
#2398
Author: Bob Calbridge
Date: Wed, 27 Mar 1996 00:57
37 lines
2278 bytes
I'm currently taking a C++ class in order to teach it next Fall.
I've taught C programming for the last three years so I know a bit
more than some of the people who program in it that they bring in to
teach it.   The class I'm in got into a discussion that I, as a fellow
"student" had a hard time explaining to the class.

The issue revolves around an if statement with a predicate that may
look like the following:

    if (value || ( GetState (value) && dumb == !smart)) {.....

The instructor agrees with me, as I'm sure everyone else here would,
that if value evaluates to true the function GetState() will never
execute due to short circuiting of the logical operators.  A few
people in the class pointed out that the parenthetical nature of the
expression on the right of the || should force it to be evaluated
first.  I know that the standard says that logical operators guarantee
that the evaluation must be performed left to right and stops when the
expression reaches a guaranteed true or a guaranteed false.  I'm not
positive on this, but I suspect that a logical operator imposes a
sequence point that forces the evaluation of the left side.  (Please
confirm if this is true.)  

I wrote a short program to prove this and the instructor demoed it in
class.  Unfortunately, I don't believe the instructor is familiar with
sequence points, though he is aware of their consequences, and has had
a hard time explaining it to the class.  ITMT, some class members are
losing confidence in the book and its author.  Truth to tell, this is
the first time I've been inclined to write to an author and get him
straight on some issue.  This one tends to over simplify and backs up
some loose conceptions with bad examples.

AAR, can someone quote chapter and verse on what covers this
situation?  Any better explanation?

TIA,
Bob
Re: Explaining precedence vs. sequence
#2408
Author: Justin C Lloyd
Date: Wed, 27 Mar 1996 12:34
59 lines
3454 bytes
On 26 Mar 1996 18:57:34 -0600, Bob Calbridge (bcalbridge@dcccd.edu) wrote:
** I'm currently taking a C++ class in order to teach it next Fall.
** I've taught C programming for the last three years so I know a bit
** more than some of the people who program in it that they bring in to
** teach it.   The class I'm in got into a discussion that I, as a fellow
** "student" had a hard time explaining to the class.

** The issue revolves around an if statement with a predicate that may
** look like the following:

**     if (value || ( GetState (value) && dumb == !smart)) {.....

** The instructor agrees with me, as I'm sure everyone else here would,
** that if value evaluates to true the function GetState() will never
** execute due to short circuiting of the logical operators.  A few
** people in the class pointed out that the parenthetical nature of the
** expression on the right of the || should force it to be evaluated
** first.  I know that the standard says that logical operators guarantee
** that the evaluation must be performed left to right and stops when the
** expression reaches a guaranteed true or a guaranteed false.  I'm not
** positive on this, but I suspect that a logical operator imposes a
** sequence point that forces the evaluation of the left side.  (Please
** confirm if this is true.)  

** I wrote a short program to prove this and the instructor demoed it in
** class.  Unfortunately, I don't believe the instructor is familiar with
** sequence points, though he is aware of their consequences, and has had
** a hard time explaining it to the class.  ITMT, some class members are
** losing confidence in the book and its author.  Truth to tell, this is
** the first time I've been inclined to write to an author and get him
** straight on some issue.  This one tends to over simplify and backs up
** some loose conceptions with bad examples.

** AAR, can someone quote chapter and verse on what covers this
** situation?  Any better explanation?

** TIA,
** Bob

Look in sections 7.7 and 7.12.1 of "C: A Reference Manual" (H&S).  They
fully explain what you are looking for. I'll quote a bit of it:

Section 7.7 Logical Operator Expressions

"The left operand of || is fully evaluated first. If the value of the left
operand is not equal to zero (in the sense of the != operator), then the
right operand is not evaluated and the result value is 1. If the left
operand is equal to zero, then the right operand is evaluated. The result
value is 1 if the right operand is not equal to zero, and is 0 otherwise."

7.12.1 talks about sequence points and refers to 7.7.

JcL

--
%%%% Justin Lloyd %% lloyd@cs.fsu.edu %% http://www.cs.fsu.edu/~lloyd %%%%
%%%  in the face of the blinding sun i wake  :     Sarah McLachlan     %%%
%%%  only to find that heaven is a stranger  :     -- Drawn to --      %%%
%%%  place than the world i've left behind   :     - the Rhythm -      %%%
Re: Explaining precedence vs. sequence
#2407
Author: Jos A. Horsmeier
Date: Wed, 27 Mar 1996 12:34
100 lines
4027 bytes
In article <4ja3pu$p8r@solutions.solon.com>, bcalbridge@dcccd.edu wrote:

I'm currently taking a C++ class in order to teach it next Fall.
I've taught C programming for the last three years so I know a bit
more than some of the people who program in it that they bring in to
teach it.   The class I'm in got into a discussion that I, as a fellow
"student" had a hard time explaining to the class.

The issue revolves around an if statement with a predicate that may
look like the following:

    if (value || ( GetState (value) && dumb == !smart)) {.....

|[ ... ] A few
|people in the class pointed out that the parenthetical nature of the
|expression on the right of the || should force it to be evaluated
|first.I know that the standard says that logical operators guarantee
|that the evaluation must be performed left to right and stops when the
|expression reaches a guaranteed true or a guaranteed false.  I'm not
|positive on this, but I suspect that a logical operator imposes a
|sequence point that forces the evaluation of the left side.  (Please
|confirm if this is true.)  

|AAR, can someone quote chapter and verse on what covers this
|situation?  Any better explanation?

If we're still talking C here, the following applies:

ISO/IEC 9899: Paragraphs 6.3.13 and 6.3.14 Logical and (or) operator

'[ ... ] the && (||) operator guarantees left-to-right evaluation;
there is a sequence point after the evaluation of the first operand.
If the first operand compares (un)equal to 0, the second operand
is not evaluated.'

The following paragraph tells the rest of the story:

ISO/IEC 9899: Paragraph 6.3 Expressions

' Except as indicated by the syntax(35) or otherwise specified later [ ... ]
the order of evaluation of subexpressions and the order in which
side effects take place are both unspecified.'

Footnote 35 reads:

'The syntax spcifies the precedence of operators in the evaluation of
an expression [ .. ].'

Parentheses don't do much actually:

ISO/IEC 9899: Paragraph 6.3.1 Primary expressions

'A parenthesized expression is a primary expression. Its type and value
are identical to thos of the unparenthesized expression.'

Combining your example, the paragraphs above and the syntax of the
individual operators, all we can deduce is, that we can safely remove
the parentheses in the example:

    if (value || GetState (value) && dumb == !smart) {.....

but still the conclusion must be: if value != 0 then the rest of
the conditional expression is not evaluated.

If people think that parenthesizing sub-expressions do wonders, show
them this:

	#include <stdio.h>

	int f() { printf("f"); return 1; }
	int g() { printf("g"); return 2; }
	int h() { printf("h"); return 3; }

	int main() {

	printf("f+g*h= %d\n", f()+g()*h());
	printf("f+(g*h)= %d\n", f()+(g()*h()));

	return 0;
	
	}

Both results of both expressions equal 7, but on my machines (RS6000/320,
SP/2, Sun 690MP, Sun 4/280, Sun Sparc 5, Sun SLC, etc. etc. etc. using cc,
gcc, xlc) function f() is called first during the evaluation of both 
expressions ... This just proves that either your fellow students are 
all wrong or my machines/compilers _and_ the Standard is wrong ... 

But if I translate this last sentence to C, like this:

	if (StudWrong || StdrdWrong && MyStuffWrong) { ...

I can see the similarity with your example and my conclusion is that
your fellow students are wrong. ;-)

kind regards,

Jos aka jos@and.nl
-- 
Atnwgqkrl gy zit vgksr, ug qshiqwtzoeqs!
Re: Explaining precedence vs. sequence
#2459
Author: Lawrence Kirby
Date: Tue, 02 Apr 1996 01:55
83 lines
3647 bytes
In article <4ja3pu$p8r@solutions.solon.com>
           bcalbridge@dcccd.edu "Bob Calbridge" writes:

>I'm currently taking a C++ class in order to teach it next Fall.
>I've taught C programming for the last three years so I know a bit
>more than some of the people who program in it that they bring in to
>teach it.   The class I'm in got into a discussion that I, as a fellow
>"student" had a hard time explaining to the class.
>
>The issue revolves around an if statement with a predicate that may
>look like the following:
>
>    if (value || ( GetState (value) && dumb == !smart)) {.....

Those other explanations looked rather complex and involved (well at least
to me!) ;-)

In the example expression || has 2 operands:

 LHS:  value

 RHS:  ( GetState (value) && dumb == !smart))

|| evaluates its RHS only if the LHS evaluates to zero.

>The instructor agrees with me, as I'm sure everyone else here would,
>that if value evaluates to true the function GetState() will never
>execute due to short circuiting of the logical operators.

Right, except that it is the whole sub-expression that forms the RHS operand
that is short-circuited.

In the expression && has 2 operands:

 LHS:  GetState (value)

 RHS:  dumb == !smart

|| evaluates its RHS only if the LHS evaluates to non-zero.

>I'm not
>positive on this, but I suspect that a logical operator imposes a
>sequence point that forces the evaluation of the left side.  (Please
>confirm if this is true.)  

&& and || always evaluate their LHS operands. Of course this will only happen
if they are themselves evaluated. In the example && won't be evaluated if
|| short-circuits its RHS.

>A few
>people in the class pointed out that the parenthetical nature of the
>expression on the right of the || should force it to be evaluated
>first.

Parentheses simply force grouping in C. Beyond the implications of that
they have no effect on order of execution.

> I know that the standard says that logical operators guarantee
>that the evaluation must be performed left to right and stops when the
>expression reaches a guaranteed true or a guaranteed false.

That's an oversimplification. && and || guarantee that their LHS is
evaluated before their RHS is (possibly) evaluated and that there is a
sequence point after the LHS is evaluated. Consider:

      if ((p1 && p2) || (p3 && p4))

If p1 evaluates to zero then p2 will not be evaluated. However p3 will
be evaluated and p4 may be evaluated. Hence left to right evaluation
is only applicable to a single operator and its operands not to the
expression as a whole. A question for you: what are the possible
orders of evaluation of:

      if ((p1 && p2) | (p3 && p4))

(note single |) or, if you prefer, what are the constraints on the order of
evaluation?

-- 
-----------------------------------------
Lawrence Kirby | fred@genesis.demon.co.uk
Wilts, England | 70734.126@compuserve.com
-----------------------------------------
Re: Explaining precedence vs. sequence
#2486
Author: Kazimir Kylheku
Date: Wed, 03 Apr 1996 13:28
53 lines
2466 bytes
In article <4jq1fe$a48@solutions.solon.com>,
Lawrence Kirby  <fred@genesis.demon.co.uk> wrote:
 >In article <4ja3pu$p8r@solutions.solon.com>
 >           bcalbridge@dcccd.edu "Bob Calbridge" writes:
 >
 >>I'm currently taking a C++ class in order to teach it next Fall.
 >>I've taught C programming for the last three years so I know a bit
 >>more than some of the people who program in it that they bring in to
 >>teach it.   The class I'm in got into a discussion that I, as a fellow
 >>"student" had a hard time explaining to the class.
 >>
 >>The issue revolves around an if statement with a predicate that may
 >>look like the following:
 >>
 >>    if (value || ( GetState (value) && dumb == !smart)) {.....
 >
 >Those other explanations looked rather complex and involved (well at least
 >to me!) ;-)
 >
 >In the example expression || has 2 operands:
 >
 > LHS:  value
 >
 > RHS:  ( GetState (value) && dumb == !smart))
 >
 >|| evaluates its RHS only if the LHS evaluates to zero.
 >
 >>The instructor agrees with me, as I'm sure everyone else here would,
 >>that if value evaluates to true the function GetState() will never
 >>execute due to short circuiting of the logical operators.
 >
 >Right, except that it is the whole sub-expression that forms the RHS operand
 >that is short-circuited.

I think that the whole problem here is a confusion between parsing (syntax) and
valuation order (semantics), which can be ``decoupled''.

The evaluation order in this case is partly bottom-up (the values are
synthesized starting from leaf nodes, working their way up), but partly
dictated by semantics that work top-down.

If you allow, I will write a piece of pseudo code to simulate:

function eval (tree T) : integer
	if T.operator = '||' then
		if (!eval(T.left)) then
			return eval(T.right)
		else
			return TRUE;
		endif
	elsif T.operator = '*' then
		return eval(T.right) * eval(T.left);
	endif
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads