Beginner post-increment question

Discussion in 'C Programming' started by Stang1, Jan 15, 2008.

  1. Stang1

    Stang1 Guest

    The following statement:

    line_buf[line_len++] = ' ';


    is equivalent to:

    line_buf[line_len] = ' ';
    line_len++;

    because post-increments are done AFTER the non-incremented values are
    used in the statement.


    Correct?
     
    Stang1, Jan 15, 2008
    #1
    1. Advertising

  2. Stang1

    DiAvOl Guest

    yes, it's correct but note that you should avoid to:

    1) use the increment or decrement operators on a variable that appears
    more than once in an expression

    For example avoid using constructs like the following

    n = 1;
    y = n++ + n++;

    2) use the increment or decrement operators on a variable that is part
    of more than one argument of a function

    Example to avoid

    printf("%d %d\n", number, number*number++);

    The reason is because the second argument might be evaluated before
    the first one
     
    DiAvOl, Jan 15, 2008
    #2
    1. Advertising

  3. Stang1 said:

    > The following statement:
    >
    > line_buf[line_len++] = ' ';
    >
    >
    > is equivalent to:
    >
    > line_buf[line_len] = ' ';
    > line_len++;
    >
    > because post-increments are done AFTER the non-incremented values are
    > used in the statement.
    >
    >
    > Correct?


    Nearly. In fact, it's correct enough for rock n' roll.

    What follows probably seems a bit picky at present, but can matter when the
    expressions get more complicated.

    The order of evaluation is up to the implementation, provided that, at
    certain points in the program (known as "sequence points"), everything
    that should have been done by that point /has/ been done by that point.

    So, for example, a compiler could legally translate:

    line_buf[line_len++] = ' ';

    by copying the value of line_len to *two* registers, say R1 and R2,
    incrementing R1, storing R1 back into line_len, and then setting
    line_buf[R2] equal to ' '.

    Why would a compiler do this? Well, it may determine that it's the most
    efficient way to do the operation on a particular architecture. Perhaps
    the hardware can do the inc/store and the array update in parallel, or
    something.

    Your code is well-defined as written. The proper element of line_buf will
    be updated, regardless of which of many correct translations is chosen.
    But if the order in which subexpressions are evaluated matters to you,
    break it down into several statements, with one evaluation per statement.
    For example, if foo() and bar() each produced output as well as returning
    a value, then if the order in which the outputs were produced is important
    you should write: n = foo(); n += bar(); arr[n] = 6; rather than arr[foo()
    + bar()] = 6; because, in the latter, code, the compiler is free to call
    foo() and bar() in either order.

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -http://www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
     
    Richard Heathfield, Jan 15, 2008
    #3
  4. Stang1

    Guest

    DiAvOl wrote:
    > yes, it's correct but note that you should avoid to:
    >
    > 1) use the increment or decrement operators on a variable that appears
    > more than once in an expression
    >
    > For example avoid using constructs like the following
    >
    > n = 1;
    > y = n++ + n++;
    >
    > 2) use the increment or decrement operators on a variable that is part
    > of more than one argument of a function
    >
    > Example to avoid
    >
    > printf("%d %d\n", number, number*number++);
    >
    > The reason is because the second argument might be evaluated before
    > the first one


    You forgot the one thing to avoid:

    3) Never use pre or post increment as parameters to macros, as a macro
    might use the parameter more than once. As a consequence, item 2
    should be "never use increment or decrement on parameters to a
    function", as you might not know if this is a real function, or that
    this was implemented as a macro.

    Kind regards,
    Johan Borkhuis
     
    , Jan 15, 2008
    #4
  5. writes:
    [...]
    > 3) Never use pre or post increment as parameters to macros, as a macro
    > might use the parameter more than once. As a consequence, item 2
    > should be "never use increment or decrement on parameters to a
    > function", as you might not know if this is a real function, or that
    > this was implemented as a macro.


    The standard library functions may be additionally implemented as
    macros, but any such macros must evaluate each of their arguments
    exactly once (except for a very few cases that are explicitly
    documented).

    As for functions outside the standard library, they could well follow
    the same convention, in which case passing expressions with side
    effects as arguments is no more of a problem than it would be for
    standard library functions.

    Macros names are conventionally in all-caps; this is at least partly
    to remind the programmer to be cautious about side effects in
    arguments.

    If a library provides a function-like macro that evaluates its
    arguments more than once, then it had better document this fact. If
    it pretends that the macro is equivalent to a corresponding function
    when it really isn't, then that's a serious flaw in the library.

    --
    Keith Thompson (The_Other_Keith) <>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Jan 15, 2008
    #5
  6. Stang1

    pete Guest

    Stang1 wrote:
    >
    > The following statement:
    >
    > line_buf[line_len++] = ' ';
    >
    > is equivalent to:
    >
    > line_buf[line_len] = ' ';
    > line_len++;
    >
    > because post-increments are done AFTER the non-incremented values are
    > used in the statement.
    >
    > Correct?


    The equivalence is true.
    Your reason is completely wrong.

    These two expressions are also interchangebly equal:

    (line_buf[line_len++] = ' ')

    (line_buf[++line_len - 1] = ' ')

    Your original c code statement,
    had only one sequence point,
    and two assignment operations.

    The assignment operation on line_len,
    could happen either before or after
    the assignement to line buff[line_len].

    Operations and side effects between sequence points,
    can occur in any order.

    (line_len++) has a value and a side effect.
    The side effect of the expression,
    is that line_len gets incremented.
    The value of the expression,
    is the value that the expression had prior to the increment operation.
    But there is no order between the assignment operation
    and the evaluation of the expression in (line_len++).

    --
    pete
     
    pete, Jan 15, 2008
    #6
  7. Stang1

    pete Guest

    Keith Thompson wrote:
    >
    > writes:
    > [...]
    > > 3) Never use pre or post increment as parameters to macros,
    > > as a macro
    > > might use the parameter more than once. As a consequence, item 2
    > > should be "never use increment or decrement on parameters to a
    > > function", as you might not know if this is a real function, or that
    > > this was implemented as a macro.

    >
    > The standard library functions may be additionally implemented as
    > macros, but any such macros must evaluate each of their arguments
    > exactly once (except for a very few cases that are explicitly
    > documented).


    The exact number of cases, is two: getc and putc.

    The standard also explicitly states
    that the stream arguments with side effects,
    should not be used with getc and putc.

    --
    pete
     
    pete, Jan 15, 2008
    #7
  8. Stang1

    Flash Gordon Guest

    DiAvOl wrote, On 15/01/08 01:16:

    Please quote enough of the post you are replying to for your post to
    make sense on it's own. There is no guarantee that everyone will *ever*
    see the post your replying to.

    > yes, it's correct but note that you should avoid to:


    <snip>

    > 2) use the increment or decrement operators on a variable that is part
    > of more than one argument of a function
    >
    > Example to avoid
    >
    > printf("%d %d\n", number, number*number++);
    >
    > The reason is because the second argument might be evaluated before
    > the first one


    It's worse than that it's dead Jim...

    The expression
    number * number++;
    is Undefined Behaviour (i.e. *anything* can happen) because number is
    modified (by number++) and also evaluated to do something other than
    generate that new value.

    The statement
    printf("%d %d\n", number, number++);
    invokes undefined behaviour not because the arguments can be evaluated
    in any order (which they can) but because number++ is again modified and
    evalutated for something other than generating the new value between
    sequence points (the comma is a separator here and not a comma operator).

    The statement
    printf("%d %d", foo(), bar());
    does *not* invoke undefined behaviour. foo and bar could be called in
    either order, but this is only *Unspecified* behaviour so unlike with
    the previous examples the implementation is *not* free to feed your
    mother to the ravenous bug blatter beast of traal.
    --
    Flash Gordon
     
    Flash Gordon, Jan 15, 2008
    #8
  9. Stang1

    CBFalconer Guest

    Keith Thompson wrote:
    >

    .... snip ...
    >
    > The standard library functions may be additionally implemented as
    > macros, but any such macros must evaluate each of their arguments
    > exactly once (except for a very few cases that are explicitly
    > documented).


    I believe the only ones that meet that specification are putc and
    getc. All others are covered by the 'one evaluation' phrase.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Jan 15, 2008
    #9
  10. Stang1

    CBFalconer Guest

    Flash Gordon wrote:
    >

    .... snip ...
    >
    > implementation is *not* free to feed your mother to the
    > ravenous bug blatter beast of traal.


    Ahh. That explains many of my problems. :)

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Jan 15, 2008
    #10
    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. Mark Turney
    Replies:
    11
    Views:
    4,286
    dibeas
    Nov 13, 2006
  2. Replies:
    104
    Views:
    11,030
    Jordan Abel
    Oct 28, 2005
  3. Replies:
    99
    Views:
    2,511
    eliza81
    Jun 11, 2010
  4. Alf P. Steinbach /Usenet
    Replies:
    0
    Views:
    900
    Alf P. Steinbach /Usenet
    May 22, 2011
  5. Peng Yu

    post increment or pre increment?

    Peng Yu, Nov 21, 2008, in forum: Perl Misc
    Replies:
    7
    Views:
    530
    Peter J. Holzer
    Nov 23, 2008
Loading...

Share This Page