home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!mcsun!sun4nl!and!jos
- From: jos@and.nl (Jos Horsmeier)
- Newsgroups: comp.lang.c
- Subject: Re: Problem on getting video ram data
- Message-ID: <3227@dozo.and.nl>
- Date: 14 Aug 92 09:48:06 GMT
- References: <1992Aug12.170428.1@cucs17.cs.cuhk.hk>
- Organization: AND Software BV Rotterdam
- Lines: 88
-
- 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
-