From: amn@unix.brighton.ac.uk (Anthony Naggs)
Newsgroups: comp.lang.c
Subject: Problem on getting video ram data
Date: 15 Aug 92 20:12:34 GMT
Reply-To: amn@vms.brighton.ac.uk
Organization: Brighton Polytechnic, England
Cc: lou1347@cucs17.cs.cuhk.hk

lou1347@cucs17.cs.cuhk.hk queries:
> #include <stdio.h>
> main()
> {
> char a[]={10,20},*video;
> int code;
> video=a;
> code=(*video++)+((*video++ & 8)?256:0);
> printf("%d\n",code);
> }
>
> 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.

Indeed.

> 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?

No.  K&R2 does not specify an order of evaluation for ARITHMETIC expressions,
only that operator precedence is applied in combining subexpressions.
The compiler is perfectly entitled to reorder calculations, so you should not
have expressions which affect other expressions, (eg referencing a variable
which is auto-(inc/dec)-remented elsewhere in the calculation).

Most compilers will attempt to minimise the number of temporary values that
must be held during the calculation.  (Thus reducing hidden stack space used
in your programs, for storing such values, and speeding the caculation). This
usually means expressions in the deepest brackets are evaluated first.
However this is only a guide, as expression optimisation usually occurs on
the compiler's internal, (generally reverse-polish), representation.

So for "code = (*video++)+((*video++ & 8)?256:0)", your compiler may produce
an evaluation sequence similar to one of these:
                      | Left to Right sequence    | Deepest first sequence
----------------------+---------------------------+-------------------------
Step 1                | temp1 = *video;           | temp1 = *video & 8;
                      | video++;                  | video++;
                      |                           |
Step 2                | temp2 = *video & 8;       | temp1 = temp1 ? 256 : 0;
                      | video++;                  |
                      |                           |
Step 3                | temp1 += temp2 ? 256 : 0; | temp1 += *video;
                      |                           | video++;
                      |                           |
Step 4                | code = temp1;             | code = temp1;
                      |                           |
Maximum temp values   | 2                         | 1

So your calculation would be better rendered as:
    code = (*video)+((*(video+1) & 8)?256:0);
    video +=2;
or
    code = video[0]+((video[1] & 8)?256:0);
    video +=2;
and some may prefer to show the link between operations
    code = video[0]+((video[1] & 8)?256:0), video +=2;

Regards,
-- 
Anthony Naggs                    |  MAN I say what it occurs to me to say when
Janet:    amn@uk.ac.brighton.vms |      I think I hear people say things.
    or    xa329@uk.ac.city       |      More I cannot say.
Internet: amn@vms.brighton.ac.uk |
       or xa329@city.ac.uk)      |  (from The Hitch-Hiker's Guide to the Galaxy)