Arg Eval

Discussion in 'C Programming' started by rayw, Oct 21, 2005.

  1. rayw

    rayw Guest

    Could someone give me the name of a compiler/environment where this code
    [below] evaluates left to right (or, at least not right to left!) - as in
    the compiler evaluates the parameter
    list left to right. This is for a c programming class, and all the gcc
    implentations I have to hand does this right to left. So, I'd like to give
    a concrete counter example.

    #include <stdio.h>

    int main(void)
    {
    int n = 1;

    /* They'd like this to result in 1, 10, 100.
    */
    printf("%d %d %d", n, n *= 10, n *= 10);

    return 0;
    }
    rayw, Oct 21, 2005
    #1
    1. Advertising

  2. rayw <> wrote:

    > #include <stdio.h>


    > int main(void)
    > {
    > int n = 1;


    > /* They'd like this to result in 1, 10, 100.
    > */


    If "they" are your instructors, drop the class immediately and tell
    them to learn

    http://www.eskimo.com/~scs/C-faq/q3.2.html

    before they presume to teach a class on C.

    > printf("%d %d %d", n, n *= 10, n *= 10);


    This is Bad Code and you can by no means expect it to produce reliable
    results even if the compiler/implementation tells you in what order it
    evaluates the function arguments (and it might not, as the Standard
    permits it to do).

    > return 0;
    > }


    --
    Christopher Benson-Manica | I *should* know what I'm talking about - if I
    ataru(at)cyberspace.org | don't, I need to know. Flames welcome.
    Christopher Benson-Manica, Oct 22, 2005
    #2
    1. Advertising

  3. rayw

    Mike Wahler Guest

    "rayw" <> wrote in message
    news:djbpg3$jrb$...
    > Could someone give me the name of a compiler/environment where this code
    > [below] evaluates left to right (or, at least not right to left!) - as in
    > the compiler evaluates the parameter
    > list left to right. This is for a c programming class,


    If your instructor is telling you to write code
    that depends upon that, you need a new instructor.

    > and all the gcc
    > implentations I have to hand does this right to left. So, I'd like to
    > give
    > a concrete counter example.


    The language standard does not specify order of
    evaluation of function arguments; therefore one
    should not write code that depends upon it.

    >
    > #include <stdio.h>
    >
    > int main(void)
    > {
    > int n = 1;
    >
    > /* They'd like this to result in 1, 10, 100.
    > */
    > printf("%d %d %d", n, n *= 10, n *= 10);
    >
    > return 0;


    printf("%d %d %d", n, n * 10, n * 10 * 10);

    or

    printf("%d %d %d", n, n * 10, n * 100);

    This will always produce:
    1 10 100

    .... no matter the compiler.

    -Mike
    Mike Wahler, Oct 22, 2005
    #3
  4. rayw

    Flash Gordon Guest

    rayw wrote:
    > Could someone give me the name of a compiler/environment where this code
    > [below] evaluates left to right (or, at least not right to left!) - as in
    > the compiler evaluates the parameter
    > list left to right.


    Not here, or at least not reliably, since the order of evaluation of
    parameters in unspecified according to the standard, so the compiler
    could produce code that evaluates them in a different order on each run.

    > This is for a c programming class, and all the gcc
    > implentations I have to hand does this right to left. So, I'd like to give
    > a concrete counter example.


    If you were asked to do this in class then it was a singularly pointless
    assignment.

    > #include <stdio.h>
    >
    > int main(void)
    > {
    > int n = 1;
    >
    > /* They'd like this to result in 1, 10, 100.
    > */
    > printf("%d %d %d", n, n *= 10, n *= 10);


    This invokes undefined behaviour, which means that literally anything
    can happen.
    1) n is modified twice without an intervening sequence point which is
    undefined behaviour
    2) n is used for a purpose other than calculating the new value of n
    which I believe also invokes undefined behaviour.

    I can certainly real ways it could produce 10 10 10 as output.

    This is all strongly related to stuff in the comp.lang.c FAQ, most
    explicitly http://www.eskimo.com/~scs/C-faq/q3.2.html

    > return 0;
    > }
    >
    >
    >



    --
    Flash Gordon
    Living in interesting times.
    Although my email address says spam, it is real and I read it.
    Flash Gordon, Oct 22, 2005
    #4
  5. On Fri, 21 Oct 2005 23:18:43 +0100, "rayw" <>
    wrote:

    >Could someone give me the name of a compiler/environment where this code
    >[below] evaluates left to right (or, at least not right to left!) - as in
    >the compiler evaluates the parameter
    >list left to right. This is for a c programming class, and all the gcc
    >implentations I have to hand does this right to left. So, I'd like to give
    >a concrete counter example.
    >
    >#include <stdio.h>
    >
    >int main(void)
    >{
    > int n = 1;
    >
    > /* They'd like this to result in 1, 10, 100.
    > */
    > printf("%d %d %d", n, n *= 10, n *= 10);


    Since this code invokes undefined behavior, you are on a wild goose
    chase from the beginning.

    >
    > return 0;
    >}
    >
    >



    <<Remove the del for email>>
    Barry Schwarz, Oct 22, 2005
    #5
  6. rayw

    Razzer Guest

    Flash Gordon wrote:
    > rayw wrote:
    >
    > > #include <stdio.h>
    > >
    > > int main(void)
    > > {
    > > int n = 1;
    > >
    > > /* They'd like this to result in 1, 10, 100.
    > > */
    > > printf("%d %d %d", n, n *= 10, n *= 10);

    >
    > This invokes undefined behaviour, which means that literally anything
    > can happen.
    > 1) n is modified twice without an intervening sequence point which is
    > undefined behaviour


    Isn't the comma operator a sequence point? Moreover, isn't the passing
    each argument a sequence point in of itself?

    > 2) n is used for a purpose other than calculating the new value of n
    > which I believe also invokes undefined behaviour.


    Only if it is in the same expression.
    Razzer, Oct 22, 2005
    #6
  7. rayw

    Artie Gold Guest

    Razzer wrote:
    > Flash Gordon wrote:
    >
    >>rayw wrote:
    >>
    >>
    >>>#include <stdio.h>
    >>>
    >>>int main(void)
    >>>{
    >>> int n = 1;
    >>>
    >>> /* They'd like this to result in 1, 10, 100.
    >>> */
    >>> printf("%d %d %d", n, n *= 10, n *= 10);

    >>
    >>This invokes undefined behaviour, which means that literally anything
    >>can happen.
    >>1) n is modified twice without an intervening sequence point which is
    >> undefined behaviour

    >
    >
    > Isn't the comma operator a sequence point? Moreover, isn't the passing
    > each argument a sequence point in of itself?
    >

    The comma operator is indeed a sequence point. The comma(s) in an
    argument list, however, are *not* comma operators. Different animal.
    >

    [snip]

    HTH,
    --ag


    --
    Artie Gold -- Austin, Texas
    http://goldsays.blogspot.com (new post 8/5)
    http://www.cafepress.com/goldsays
    "If you have nothing to hide, you're not trying!"
    Artie Gold, Oct 22, 2005
    #7
  8. rayw

    Razzer Guest

    Artie Gold wrote:
    > Razzer wrote:
    > > Flash Gordon wrote:
    > >
    > >>rayw wrote:
    > >>
    > >>
    > >>>#include <stdio.h>
    > >>>
    > >>>int main(void)
    > >>>{
    > >>> int n = 1;
    > >>>
    > >>> /* They'd like this to result in 1, 10, 100.
    > >>> */
    > >>> printf("%d %d %d", n, n *= 10, n *= 10);
    > >>
    > >>This invokes undefined behaviour, which means that literally anything
    > >>can happen.
    > >>1) n is modified twice without an intervening sequence point which is
    > >> undefined behaviour

    > >
    > >
    > > Isn't the comma operator a sequence point? Moreover, isn't the passing
    > > each argument a sequence point in of itself?
    > >

    > The comma operator is indeed a sequence point. The comma(s) in an
    > argument list, however, are *not* comma operators. Different animal.


    You're right. I was trying to make an analogy between the two, although
    I should've been more explicit.

    > >

    > [snip]
    >
    > HTH,
    > --ag
    >
    >
    > --
    > Artie Gold -- Austin, Texas
    > http://goldsays.blogspot.com (new post 8/5)
    > http://www.cafepress.com/goldsays
    > "If you have nothing to hide, you're not trying!"
    Razzer, Oct 22, 2005
    #8
  9. rayw

    Mike Wahler Guest

    "Razzer" <> wrote in message
    news:...
    >
    > Flash Gordon wrote:
    >> rayw wrote:
    >>
    >> > #include <stdio.h>
    >> >
    >> > int main(void)
    >> > {
    >> > int n = 1;
    >> >
    >> > /* They'd like this to result in 1, 10, 100.
    >> > */
    >> > printf("%d %d %d", n, n *= 10, n *= 10);

    >>
    >> This invokes undefined behaviour, which means that literally anything
    >> can happen.
    >> 1) n is modified twice without an intervening sequence point which is
    >> undefined behaviour

    >
    > Isn't the comma operator a sequence point?


    There are no occurrences of the comma operator in that code.

    > Moreover, isn't the passing
    > each argument a sequence point in of itself?


    No.

    -Mike
    Mike Wahler, Oct 22, 2005
    #9
  10. Razzer wrote:
    > Flash Gordon wrote:
    >
    >>rayw wrote:


    >>> printf("%d %d %d", n, n *= 10, n *= 10);


    >>This invokes undefined behaviour, which means that literally anything
    >>can happen.
    >>1) n is modified twice without an intervening sequence point which is
    >> undefined behaviour


    > Isn't the comma operator a sequence point? Moreover, isn't the passing
    > each argument a sequence point in of itself?


    There is no comma operator anywhere in that statement, so whether a
    comma operator marks a sequence point is irrelevant.
    Martin Ambuhl, Oct 22, 2005
    #10
  11. >> > #include <stdio.h>
    >> >
    >> > int main(void)
    >> > {
    >> > int n = 1;
    >> >
    >> > /* They'd like this to result in 1, 10, 100.
    >> > */
    >> > printf("%d %d %d", n, n *= 10, n *= 10);

    >>
    >> This invokes undefined behaviour, which means that literally anything
    >> can happen.
    >> 1) n is modified twice without an intervening sequence point which is
    >> undefined behaviour

    >
    >Isn't the comma operator a sequence point?


    There are no comma operators in the above code.

    >Moreover, isn't the passing
    >each argument a sequence point in of itself?


    No.

    Gordon L. Burditt
    Gordon Burditt, Oct 22, 2005
    #11
  12. rayw

    Chris Torek Guest

    In article <djbpg3$jrb$> rayw <> wrote:
    >Could someone give me the name of a compiler/environment where this code
    >[below] evaluates left to right (or, at least not right to left!) ...
    >all the gcc implentations I have to hand does this right to left.
    >So, I'd like to give a concrete counter example.
    >
    >#include <stdio.h>
    >
    >int main(void)
    >{
    > int n = 1;
    >
    > /* They'd like this to result in 1, 10, 100.
    > */
    > printf("%d %d %d", n, n *= 10, n *= 10);
    >
    > return 0;
    >}


    Indeed, as everyone else has noted, this results in undefined
    behavior. The question, however, is whether someone has an example
    system on which (a) output is produced, and (b) the output is
    "1 10 100". (It would help to add a newline.)

    The old Pyramid C compiler would have done that, as it evaluated
    the first 12 arguments left-to-right. Arguments beyond the first
    twelve were evaluated right-to-left (and before the first twelve
    were handled left-to-right). This was because most parameters are
    passed in the Parameter Registers, pr0 through pr11 inclusive,
    while those that do not fit are passed on a conventional stack.
    (In the callee, the registers are named pr0 through pr11 -- the
    caller addresses them as tr0 through tr11, the temporary or transfer
    registers. Normally these are available for scratch computations.
    Return values go in pr0 so that the caller sees them in tr0.)

    It is generally difficult to find compilers that work strictly
    L-to-R: good compilers often seem to do the evaluation in "apparently
    random order", while poor compilers usually do them in whatever
    order is easiest on the target hardware, and common target hardware
    happens to cause the latter to be R-to-L.

    Presumably the reason for the desire for "1 10 100" output is to
    demonstrate that not all compilers produce "100 10 1", in an effort
    to convince programmers that they should avoid such code. But
    those who will not be convinced by the text of the C Standards
    might also not be convinced by counterexamples: "Why, those compilers
    are just broken," they might say.

    Still, one handy counterexample I have is a Mac G4 (PowerPC) running
    OS X 10.2 (one of these days I should upgrade it). After fixing
    the code above to include a terminating newline, and compiling with
    "cc" (which is Apple GCC version 1175 "based on gcc version 3.1
    20020420 (prerelease)"), I get:

    % cc -o t t.c
    % ./t
    100 10 100

    The output remains unchanged when optimized (with -O or -O2).

    The PowerPC, MIPS, and SPARC are three good architectures to
    try, as all three generally use registers for parameter-passing.

    Note that calling a function other than printf() might change the
    result on some machines, because printf() is a variable-argument
    function, and there are good reasons to want to use different
    calling conventions for fixed vs variable argument functions.
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
    Chris Torek, Oct 22, 2005
    #12
  13. rayw

    Flash Gordon Guest

    Razzer wrote:
    > Flash Gordon wrote:
    >
    >>rayw wrote:
    >>
    >>>#include <stdio.h>
    >>>
    >>>int main(void)
    >>>{
    >>> int n = 1;
    >>>
    >>> /* They'd like this to result in 1, 10, 100.
    >>> */
    >>> printf("%d %d %d", n, n *= 10, n *= 10);

    >>
    >>This invokes undefined behaviour, which means that literally anything
    >>can happen.
    >>1) n is modified twice without an intervening sequence point which is
    >> undefined behaviour

    >
    > Isn't the comma operator a sequence point? Moreover, isn't the passing
    > each argument a sequence point in of itself?


    Other have noted there is no comma operator and there no sequence point
    between evaluation of parameters.

    >>2) n is used for a purpose other than calculating the new value of n
    >> which I believe also invokes undefined behaviour.

    >
    > Only if it is in the same expression.


    No, between sequence points. In section 6.5 of N1224 it says
    | 2 Between the previous and next sequence point an object shall have
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    | its stored value modified at most once by the evaluation of an
    | expression. Furthermore, the prior value shall be read only to
    | determine the value to be stored.71)

    No where does it say this only applies to individual expressions. If it
    did then it would make this explicit. So
    printf("%d %d", n, n *= 10);
    would also be undefined behaviour in my opinion since you are reading n
    for a purpose other than calculating its new value between sequence points.
    --
    Flash Gordon
    Living in interesting times.
    Although my email address says spam, it is real and I read it.
    Flash Gordon, Oct 22, 2005
    #13
  14. rayw

    rayw Guest

    "Chris Torek" <> wrote in message
    news:...
    > In article <djbpg3$jrb$> rayw <>
    > wrote:
    >>Could someone give me the name of a compiler/environment where this code
    >>[below] evaluates left to right (or, at least not right to left!) ...
    >>all the gcc implentations I have to hand does this right to left.
    >>So, I'd like to give a concrete counter example.
    >>
    >>#include <stdio.h>
    >>
    >>int main(void)
    >>{
    >> int n = 1;
    >>
    >> /* They'd like this to result in 1, 10, 100.
    >> */
    >> printf("%d %d %d", n, n *= 10, n *= 10);
    >>
    >> return 0;
    >>}

    >
    > Indeed, as everyone else has noted, this results in undefined
    > behavior. The question, however, is whether someone has an example
    > system on which (a) output is produced, and (b) the output is
    > "1 10 100". (It would help to add a newline.)
    >
    > The old Pyramid C compiler would have done that, as it evaluated
    > the first 12 arguments left-to-right. Arguments beyond the first
    > twelve were evaluated right-to-left (and before the first twelve
    > were handled left-to-right). This was because most parameters are
    > passed in the Parameter Registers, pr0 through pr11 inclusive,
    > while those that do not fit are passed on a conventional stack.
    > (In the callee, the registers are named pr0 through pr11 -- the
    > caller addresses them as tr0 through tr11, the temporary or transfer
    > registers. Normally these are available for scratch computations.
    > Return values go in pr0 so that the caller sees them in tr0.)
    >
    > It is generally difficult to find compilers that work strictly
    > L-to-R: good compilers often seem to do the evaluation in "apparently
    > random order", while poor compilers usually do them in whatever
    > order is easiest on the target hardware, and common target hardware
    > happens to cause the latter to be R-to-L.
    >
    > Presumably the reason for the desire for "1 10 100" output is to
    > demonstrate that not all compilers produce "100 10 1", in an effort
    > to convince programmers that they should avoid such code. But
    > those who will not be convinced by the text of the C Standards
    > might also not be convinced by counterexamples: "Why, those compilers
    > are just broken," they might say.
    >
    > Still, one handy counterexample I have is a Mac G4 (PowerPC) running
    > OS X 10.2 (one of these days I should upgrade it). After fixing
    > the code above to include a terminating newline, and compiling with
    > "cc" (which is Apple GCC version 1175 "based on gcc version 3.1
    > 20020420 (prerelease)"), I get:
    >
    > % cc -o t t.c
    > % ./t
    > 100 10 100
    >
    > The output remains unchanged when optimized (with -O or -O2).
    >
    > The PowerPC, MIPS, and SPARC are three good architectures to
    > try, as all three generally use registers for parameter-passing.
    >
    > Note that calling a function other than printf() might change the
    > result on some machines, because printf() is a variable-argument
    > function, and there are good reasons to want to use different
    > calling conventions for fixed vs variable argument functions.


    That's just the job - ta.

    I should have made it clear that I'm teaching this course, and that the code
    was entered by a student. Obviously, I explained the mistake, and then
    actually walked through what was happening here with the class.

    All I was after -just for interest'ss sake- was the name of a compiler that
    happened to eval left to right.

    rayw
    rayw, Oct 23, 2005
    #14
  15. rayw

    Jalapeno Guest

    rayw wrote:
    > Could someone give me the name of a compiler/environment where this code
    > [below] evaluates left to right (or, at least not right to left!) - as in
    > the compiler evaluates the parameter
    > list left to right. This is for a c programming class, and all the gcc
    > implentations I have to hand does this right to left. So, I'd like to give
    > a concrete counter example.
    >
    > #include <stdio.h>
    >
    > int main(void)
    > {
    > int n = 1;
    >
    > /* They'd like this to result in 1, 10, 100.
    > */
    > printf("%d %d %d", n, n *= 10, n *= 10);
    >
    > return 0;
    > }


    The z/OS C version 1 release 6 compiler from IBM for their Mainframes:
    (This was compiled and run in batch under JES2)

    5694A01 V1 R6 z/OS C 'SYS05297.T091012.RA000.T9232EHD.SOURCE.H02'


    * * * * * S O U R C E * * * * *


    LINE STMT


    *...+....1....+....2....+....3....+....4....+....5....+....6....+.
    1 |#include <stdio.h>

    2 |

    3 |int main(void)

    4 |{

    5 1 | int n = 1;

    6 |

    7 | /* They'd like this to result in 1, 10, 100.

    8 | */

    9 2 | printf("%d %d %d", n, n *= 10, n *= 10);

    10 |

    11 3 | return 0;

    12 |}

    * * * * * E N D O F S O U R C E * *


    Display Filter View Print Options Help
    ------------------------------------------------------------------
    SDSF OUTPUT DISPLAY T9232EHB JOB17312 DSID 102 LINE 0 COL
    COMMAND INPUT ===> SCRO
    ********************************* TOP OF DATA *********************
    1 10 100
    ******************************** BOTTOM OF DATA *******************
    Jalapeno, Oct 24, 2005
    #15
  16. rayw

    rayw Guest

    "Jalapeno" <> wrote in message
    news:...
    >
    > rayw wrote:
    >> Could someone give me the name of a compiler/environment where this code
    >> [below] evaluates left to right (or, at least not right to left!) - as in
    >> the compiler evaluates the parameter
    >> list left to right. This is for a c programming class, and all the gcc
    >> implentations I have to hand does this right to left. So, I'd like to
    >> give
    >> a concrete counter example.
    >>
    >> #include <stdio.h>
    >>
    >> int main(void)
    >> {
    >> int n = 1;
    >>
    >> /* They'd like this to result in 1, 10, 100.
    >> */
    >> printf("%d %d %d", n, n *= 10, n *= 10);
    >>
    >> return 0;
    >> }

    >
    > The z/OS C version 1 release 6 compiler from IBM for their Mainframes:
    > (This was compiled and run in batch under JES2)
    >
    > 5694A01 V1 R6 z/OS C 'SYS05297.T091012.RA000.T9232EHD.SOURCE.H02'
    >
    >
    > * * * * * S O U R C E * * * * *
    >
    >
    > LINE STMT
    >
    >
    > *...+....1....+....2....+....3....+....4....+....5....+....6....+.
    > 1 |#include <stdio.h>
    >
    > 2 |
    >
    > 3 |int main(void)
    >
    > 4 |{
    >
    > 5 1 | int n = 1;
    >
    > 6 |
    >
    > 7 | /* They'd like this to result in 1, 10, 100.
    >
    > 8 | */
    >
    > 9 2 | printf("%d %d %d", n, n *= 10, n *= 10);
    >
    > 10 |
    >
    > 11 3 | return 0;
    >
    > 12 |}
    >
    > * * * * * E N D O F S O U R C E * *
    >
    >
    > Display Filter View Print Options Help
    > ------------------------------------------------------------------
    > SDSF OUTPUT DISPLAY T9232EHB JOB17312 DSID 102 LINE 0 COL
    > COMMAND INPUT ===> SCRO
    > ********************************* TOP OF DATA *********************
    > 1 10 100
    > ******************************** BOTTOM OF DATA *******************
    >


    Excellent - thanks!
    rayw, Oct 24, 2005
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Eric Newton
    Replies:
    3
    Views:
    9,344
    Brock Allen
    Apr 4, 2005
  2. DataBinder.Eval and Eval.

    , Jun 16, 2006, in forum: ASP .Net
    Replies:
    1
    Views:
    519
    Karl Seguin [MVP]
    Jun 16, 2006
  3. n00m
    Replies:
    5
    Views:
    384
  4. Replies:
    7
    Views:
    161
  5. Replies:
    21
    Views:
    268
    Barry Schwarz
    Mar 5, 2014
Loading...

Share This Page