From: jos@and.nl (Jos Horsmeier)
Newsgroups: comp.lang.c
Subject: Re: Problem on getting video ram data
Date: 14 Aug 92 09:48:06 GMT
Organization: AND Software BV Rotterdam

In article <1992Aug12.170428.1@cucs17.cs.cuhk.hk> lou1347@cucs17.cs.cuhk.hk 
originally asked why this doesn't work:

  code=(*video++)+(*video++ & 8)?256:0;

Someone else replied:

|According to "The C Pocket Reference" by Herbert Schildt,
|Osborne McGraw-Hill, ?: operator's presedence is lower than
|+'s, so code is either 256 or 0.

And the answer to that is:

|Thanks, but I still in trouble.  I wrote another test program like that:
|
|code=(*video++)+((*video++ & 8)?256:0);
|
|The bracket is added.  I expect the result to be 10.  But It give 276!!
|(If I split it into two lines, the result will be 10).
|
|I think the problem is that the operand after '+' do first so that the 
|first *video got 20 and second *video got 10 which give the result 276.
|
|But I know that in C,'+' sign will do from left to right.  ( I also write a
|program to test it and it is true )  So what is the result?

I can predict you, that result is implementation dependent.
The addition and subtraction operators are just left-associative.
This just means that a+b-c will be evaluated as (a+b)-c, but it 
says nothing about the order in which the individual operands are
evaluated. 

The problem with your original code is, you're trying to squeeze too
much functionality in one expression. The standard says:

ANSI-C 2.1.2.3 Program execution

[ ... ] At certain specified points in the execution sequence called
_sequence points_, all side effects of previous evaluations shall be
complete and no side effects of subsequent evaluations shall have
take place.

In a following example, they describe your problem:

The grouping of an expression does not completely determine its 
evaluation. In the following fragment

sum= sum * 10 - '0' + (*p++= getchar());

the expression statement is grouped as if it were written as

sum= (((sum * 10) - '0') + ((*(p++)) = (getchar())));

but the actual increment of p can occur at any time between the previous
sequence point and the next sequence point (the ;) and the call to 
getchar can occur at any point prior to the need of its returned value.

[ end quote ]

Your code fragement `*video++' occurs even _twice_ between two sequence
points. The postfix ++ operator is a hidden assignment. About assignments,
the standard says the following:

3.3.16 Assignment operators

[ ... ] The side effect of updating the stored value of the left operand
shall occur between the previous and the next sequence point.

So, your compiler is free to fetch the value of the video variable,
register the fact somewhere that this variable needs to be incremented
later and goes on with the show. This increment is not necessarily done
right after fetching the old value, it can be done just when the sequence
point is reached (the `;' here).

You've solved your problem yourself already: you've split the assignment
expression in two, and that was the only correct thing you could do.

moral of the story: don't write code as if you were participating in the
Obfuscated C Code Contest. It doesn't make your code more efficient,
it just shrinks your source files a bit. Let the compiler do the hard
work of optimization, it can do a much better job than you and I can ever
accomplish.

I hope this clarifies things a bit,

kind regards,

Jos aka jos@and.nl