is ++n equivalent to (n=n+1) ?

Discussion in 'C Programming' started by Kobu, Feb 4, 2005.

  1. Kobu

    Kobu Guest

    Hi,

    I've gotten into the habit of mentally converting big expressions to
    parse tress (started doing this after reading some c.l.c posts on parse
    trees).

    Can someone verify if the following assumptions are correct?

    1) For ++n, one can us (n=n+1) as it's equivalent:

    | =
    | / \
    | n +
    | / \
    | n 1


    2) For assignment operators of the form n op= b, the equivalent tree
    is:

    | =
    | / \
    | n op
    | / \
    | n b

    3) For n++, one can use n, but with a side condition that (n=n+1) will
    occur somewhere between now and the earliest sequence point up the tree
    (but n=n+1 is no physically part of the tree)

    |
    | n
    |
    | [Side note: (n=n+1) can occure as a side effect anytime before the
    | earliest sequence point up the tree]



    Are my assumption correct?
    Kobu, Feb 4, 2005
    #1
    1. Advertising

  2. In article <>,
    Kobu <> wrote:
    :I've gotten into the habit of mentally converting big expressions to
    :parse tress

    :Can someone verify if the following assumptions are correct?

    :1) For ++n, one can us (n=n+1) as it's equivalent:

    No. Suppose n is an expression that returns an lvalue and which
    has side effects. In n = n + 1 then n will be evaluated for both
    sides of the assignment, resulting in the side effect being done
    twice. In n++ or n op= p n will only be evaluated once.

    For example, queuehead()->count = queuehead()->count + 1
    differs from queuehead()->count++

    --
    When your posts are all alone / and a user's on the phone/
    there's one place to check -- / Upstream!
    When you're in a hurry / and propagation is a worry/
    there's a place you can post -- / Upstream!
    Walter Roberson, Feb 4, 2005
    #2
    1. Advertising

  3. In article <>,
    "Kobu" <> wrote:

    > Hi,
    >
    > I've gotten into the habit of mentally converting big expressions to
    > parse tress (started doing this after reading some c.l.c posts on parse
    > trees).
    >
    > Can someone verify if the following assumptions are correct?
    >
    > 1) For ++n, one can us (n=n+1) as it's equivalent:
    >
    > | =
    > | / \
    > | n +
    > | / \
    > | n 1
    >
    >
    > 2) For assignment operators of the form n op= b, the equivalent tree
    > is:
    >
    > | =
    > | / \
    > | n op
    > | / \
    > | n b


    Correct, except that the lvalue n is only evaluated once. So

    ++(*++p); ++a [i++];

    is absolutely not the same as

    (*++p) = (*++p) + 1; a [i++] = a [i++] + 1;


    but for a plain variable like n it is correct. (2) is quite important if
    you need to figure out exactly what happens for example if you have a
    complicated case like

    unsigned short us;
    double d;

    us += d;

    In a case like that, all you need to do is to read what exactly (us + d)
    does, and then you read the rules what assigning a double to an unsigned
    short exactly does. Defining it this way must have saved dozens of pages
    in the C Standard.

    > 3) For n++, one can use n, but with a side condition that (n=n+1) will
    > occur somewhere between now and the earliest sequence point up the tree
    > (but n=n+1 is no physically part of the tree)
    >
    > |
    > | n
    > |
    > | [Side note: (n=n+1) can occure as a side effect anytime before the
    > | earliest sequence point up the tree]


    Yes.
    Christian Bau, Feb 4, 2005
    #3
  4. Kobu

    Kobu Guest

    Christian Bau wrote:
    > In article <>,
    > "Kobu" <> wrote:
    >
    > > Hi,
    > >
    > > I've gotten into the habit of mentally converting big expressions

    to
    > > parse tress (started doing this after reading some c.l.c posts on

    parse
    > > trees).
    > >
    > > Can someone verify if the following assumptions are correct?
    > >
    > > 1) For ++n, one can us (n=n+1) as it's equivalent:
    > >
    > > | =
    > > | / \
    > > | n +
    > > | / \
    > > | n 1
    > >
    > >
    > > 2) For assignment operators of the form n op= b, the equivalent

    tree
    > > is:
    > >
    > > | =
    > > | / \
    > > | n op
    > > | / \
    > > | n b

    >
    > Correct, except that the lvalue n is only evaluated once. So
    >
    > ++(*++p); ++a [i++];
    >
    > is absolutely not the same as
    >
    > (*++p) = (*++p) + 1; a [i++] = a [i++] + 1;
    >
    >
    > but for a plain variable like n it is correct. (2) is quite important

    if
    > you need to figure out exactly what happens for example if you have a


    > complicated case like
    >
    > unsigned short us;
    > double d;
    >
    > us += d;
    >
    > In a case like that, all you need to do is to read what exactly (us +

    d)
    > does, and then you read the rules what assigning a double to an

    unsigned
    > short exactly does. Defining it this way must have saved dozens of

    pages
    > in the C Standard.
    >
    > > 3) For n++, one can use n, but with a side condition that (n=n+1)

    will
    > > occur somewhere between now and the earliest sequence point up the

    tree
    > > (but n=n+1 is no physically part of the tree)
    > >
    > > |
    > > | n
    > > |
    > > | [Side note: (n=n+1) can occure as a side effect anytime before

    the
    > > | earliest sequence point up the tree]

    >
    > Yes.



    Good point, I guess I can represent (exp)++ where exp has meaning as
    an lvalue as:


    | =
    | / \
    | temp +
    | / \
    | = 1
    | / \
    | temp exp <-- exp would really be more branching
    | (executed once)


    where (exp) = (exp) + 1 would be:

    | =
    | / \
    | exp + <--
    | / \ |-- exp related branching in two places
    | exp 1 <-- (executed twice)
    |
    Kobu, Feb 5, 2005
    #4
  5. Kobu

    TTroy Guest

    Kobu wrote:
    > Christian Bau wrote:
    > > In article <>,
    > > "Kobu" <> wrote:
    > >
    > > > Hi,
    > > >
    > > > I've gotten into the habit of mentally converting big expressions

    > to
    > > > parse tress (started doing this after reading some c.l.c posts on

    > parse
    > > > trees).
    > > >
    > > > Can someone verify if the following assumptions are correct?
    > > >
    > > > 1) For ++n, one can us (n=n+1) as it's equivalent:
    > > >
    > > > | =
    > > > | / \
    > > > | n +
    > > > | / \
    > > > | n 1
    > > >
    > > >
    > > > 2) For assignment operators of the form n op= b, the equivalent

    > tree
    > > > is:
    > > >
    > > > | =
    > > > | / \
    > > > | n op
    > > > | / \
    > > > | n b

    > >
    > > Correct, except that the lvalue n is only evaluated once. So
    > >
    > > ++(*++p); ++a [i++];
    > >
    > > is absolutely not the same as
    > >
    > > (*++p) = (*++p) + 1; a [i++] = a [i++] + 1;
    > >
    > >
    > > but for a plain variable like n it is correct. (2) is quite

    important
    > if
    > > you need to figure out exactly what happens for example if you have

    a
    >
    > > complicated case like
    > >
    > > unsigned short us;
    > > double d;
    > >
    > > us += d;
    > >
    > > In a case like that, all you need to do is to read what exactly (us

    +
    > d)
    > > does, and then you read the rules what assigning a double to an

    > unsigned
    > > short exactly does. Defining it this way must have saved dozens of

    > pages
    > > in the C Standard.

    >


    snip

    >
    > Good point, I guess I can represent (exp)++ where exp has meaning

    as
    > an lvalue as:
    >
    >
    > | =
    > | / \
    > | temp +
    > | / \
    > | = 1
    > | / \
    > | temp exp <-- exp would really be more branching
    > | (executed once)
    >
    >
    > where (exp) = (exp) + 1 would be:
    >
    > | =
    > | / \
    > | exp + <--
    > | / \ |-- exp related branching in two places
    > | exp 1 <-- (executed twice)
    > |



    Does this distinction apply to (exp) op= b ? Is exp guranteed to
    evaluate only once or is (exp) op= b truly equivalent to (exp) = (exp)
    op b ?
    TTroy, Feb 5, 2005
    #5
  6. In article <>,
    TTroy <> wrote:
    :Does this distinction apply to (exp) op= b ? Is exp guranteed to
    :evaluate only once or is (exp) op= b truly equivalent to (exp) = (exp)
    :eek:p b ?

    The C89 standard says that they are equivilent -except- that (exp)
    is evaluated only once for (exp) op= b .

    --
    Suppose there was a test you could take that would report whether
    you had Free Will or were Pre-Destined. Would you take the test?
    Walter Roberson, Feb 5, 2005
    #6
  7. Kobu

    TTroy Guest

    Walter Roberson wrote:
    > In article <>,
    > Kobu <> wrote:
    >


    snipped

    >
    > No. Suppose n is an expression that returns an lvalue and which
    > has side effects. In n = n + 1 then n will be evaluated for both
    > sides of the assignment, resulting in the side effect being done
    > twice. In n++ or n op= p n will only be evaluated once.
    >
    > For example, queuehead()->count = queuehead()->count + 1
    > differs from queuehead()->count++
    >


    I've never seen that. A function name followed by the -> operator. Is
    this part of C or C++? I thought -> only goes with structures.

    >
    > --
    > When your posts are all alone / and a user's on the phone/
    > there's one place to check -- / Upstream!
    > When you're in a hurry / and propagation is a worry/
    > there's a place you can post -- / Upstream!
    TTroy, Feb 5, 2005
    #7
  8. TTroy wrote:
    [...]
    > > For example, queuehead()->count = queuehead()->count + 1
    > > differs from queuehead()->count++
    > >

    >
    > I've never seen that. A function name followed by the -> operator. Is
    > this part of C or C++? I thought -> only goes with structures.


    Hint:

    extern struct MyStruct *queuehead(void);

    --
    +-------------------------+--------------------+-----------------------------+
    | Kenneth J. Brody | www.hvcomputer.com | |
    | kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
    +-------------------------+--------------------+-----------------------------+
    Don't e-mail me at: <mailto:>
    Kenneth Brody, Feb 5, 2005
    #8
  9. In article <>,
    TTroy <> wrote:

    :Walter Roberson wrote:
    :> For example, queuehead()->count = queuehead()->count + 1

    :I've never seen that. A function name followed by the -> operator. Is
    :this part of C or C++? I thought -> only goes with structures.

    -> goes with pointers to structures. A function can return
    a pointer. In traditional C, a function could not return a structure
    directly.
    --
    Any sufficiently advanced bug is indistinguishable from a feature.
    -- Rich Kulawiec
    Walter Roberson, Feb 6, 2005
    #9
  10. Kobu

    CBFalconer Guest

    Walter Roberson wrote:
    > Kobu <> wrote:
    >
    >> I've gotten into the habit of mentally converting big expressions
    >> to parse tress

    >
    >> Can someone verify if the following assumptions are correct?

    >
    >> 1) For ++n, one can us (n=n+1) as it's equivalent:

    >
    > No. Suppose n is an expression that returns an lvalue and which
    > has side effects. In n = n + 1 then n will be evaluated for both
    > sides of the assignment, resulting in the side effect being done
    > twice. In n++ or n op= p n will only be evaluated once.


    That depends on the stupidity level of the code generator. For
    example, for n = n+1, we might generate:

    load address of n to r1
    load indirect r1 to r2
    add 1 to r2
    (load address of n to r1) only in a STUPID code generator.
    store indirect r2 via r1

    n has been evaluated only once, and the expression value is in r2.
    Now the n++ may be more complex, because of the need to use the
    original value. The compiler may detect that this is not needed,
    but...

    load address of n to r1
    load indirect r1 to r2
    copy r2 to r3
    add 1 to r2
    store indirect r2 via r1

    now the expression value is in r3. Of course all this depends
    highly on the machine language instructions available.

    Some of the important things in code generation are selecting
    registers, and remembering what is in them, and when you don't
    know. The more you can put off selecting, filling, and discarding
    registers the better the chance of doing it efficiently by finding
    out you can reuse something.

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
    CBFalconer, Feb 6, 2005
    #10
  11. Kobu

    Chris Torek Guest

    In article <>
    Kobu <> wrote:
    >Good point, I guess I can represent (exp)++ where exp has meaning as
    >an lvalue as:
    >
    >| =
    >| / \
    >| temp +
    >| / \
    >| = 1
    >| / \
    >| temp exp <-- exp would really be more branching
    >| (executed once)


    This tree is not quite right, as it never assigns a new value to
    exp.

    >where (exp) = (exp) + 1 would be:
    >
    >| =
    >| / \
    >| exp + <--
    >| / \ |-- exp related branching in two places
    >| exp 1 <-- (executed twice)
    >|


    This tree is fine.

    If you write a C compiler, you will likely discover that it is
    simplest to include tree-operators for op= expressions. (You can
    then use these for prefix ++ and --.) Whether you want to include
    separate tree-operators for postfix ++ and -- expressions is a more
    delicate matter.... (I am not sure what gcc does. By the time
    it gets to code generation, however, it has gone from tree to
    RTL; in the RTL, exp++ has been replaced with "tmp_reg = exp;
    exp = exp + 1;" anyway. You can see this by passing the "-dr"
    flag to the compiler to dump out the RTL.)
    --
    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, Feb 6, 2005
    #11
    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. Brendan Duffy

    Re: Image Scanning - TWAIN equivalent

    Brendan Duffy, Jul 24, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    1,463
    Brendan Duffy
    Jul 24, 2003
  2. Lolo
    Replies:
    3
    Views:
    571
  3. Sanjeev
    Replies:
    4
    Views:
    3,534
    Jonathan Bromley
    Jul 23, 2004
  4. Eric Peers
    Replies:
    2
    Views:
    1,297
    Jonathan Bromley
    Nov 18, 2004
  5. mag
    Replies:
    1
    Views:
    640
    Andy Peters
    May 19, 2005
Loading...

Share This Page