tricky assignment statemenent

Discussion in 'C Programming' started by ccwork, Jan 17, 2005.

  1. ccwork

    ccwork Guest

    >There are two assignments here. In one assignment, p is modified. The
    >prior value of p is arguably used to determine the new value stored

    into
    >p, as you explained, but it is _also_ read to determine at which

    memory
    >location the second assignment will happen, so it is not _only_ read

    to
    >determine the value stored, therefore undefined behavior.


    There is something wrong. The first assignment is "p->next = q" and
    "p" is _not_ modified. After this assignment value of "p" is _not_
    changed; only "p->next" is changed. The second assignemnt is "p =
    p->next =q" and "p" is going to hold the result of "p->next = q",
    which is "q".

    Consider "b = b * 10". According to your logic it will be undefined
    since b is read to determine new value but also read to determine
    memory for second assignment.
    ccwork, Jan 17, 2005
    #1
    1. Advertising

  2. ccwork

    Chris Torek Guest

    [given "p = p->next = q" for suitable pointers p and q]

    Someone -- name filed off but not by me and the person to whom I am
    replying used the badly broken Google news posting interface -- wrote:

    >>There are two assignments here. In one assignment, p is modified. The
    >>prior value of p is arguably used to determine the new value stored

    >into p, as you explained, but it is _also_ read to determine at which
    >>memory location the second assignment will happen, so it is not
    >>_only_ read to >determine the value stored, therefore undefined behavior.


    In article <>
    ccwork <> wrote:
    >There is something wrong. The first assignment is "p->next = q" and
    >"p" is _not_ modified.


    This is correct, except that the word "first" is not appropriate --
    there is no ordering implied yet.

    >After this assignment value of "p" is _not_ changed; only "p->next"
    >is changed. The second assignemnt is "p = p->next =q " and "p" is
    >going to hold the result of "p->next = q", which is "q".


    Yes. The problem comes about because (or "if", depending on how
    you read the precise text of the C89 and C99 standards) the words
    "before" and "after" are not applicable. There are those who
    claim that a C compiler can treat:

    a = b = c;

    as if it read:

    temp = c;
    a = temp;
    b = temp;

    i.e., assign to the leftmost object, then assign to the middle
    object.

    Suppose this happens with "p = p->next = q". Then we get:

    temp = q;
    p = temp;
    p->next = temp;

    which does something quite different from:

    temp = q;
    p->next = temp;
    p = temp;

    If you believe that the C standard allows this runtime order of
    operations, then the assignment "p = p->next = q" is undefined
    and sometimes does the wrong thing. If you believe that the C
    standard does not allow this runtime order of operations, then
    the assignment is well-defined and always does the right thing.

    While it would be very nice to say "clearly the folks who wrote
    the standard *meant* to say it is well-defined", we do not get to
    do that. We have to read what it actually says. Only the Anointed
    Few who have authority to respond to Defect Reports can say
    "this is what it means".

    Since it is not clear, your best bet is to avoid the construct --
    if you write:

    p->next = q;
    p = q; /* or p = p->next; */

    your code will absolute, positively work every time. This is
    probably worth the extreme exhaustion typing that extra line of
    code may cause your fingers. :)

    >Consider "b = b * 10". According to your logic it will be undefined
    >since b is read to determine new value but also read to determine
    >memory for second assignment.


    This assignment is not very analagous; a better comparison might
    be something like:

    b = (b = b * 10) + 4;

    except this is considerably worse than "p = p->next = q" (the case
    with "b" here is clearly undefined, while the case with p is not
    clear at all).
    --
    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, Jan 17, 2005
    #2
    1. Advertising

  3. In article <>,
    (ccwork) wrote:

    > >There are two assignments here. In one assignment, p is modified. The
    > >prior value of p is arguably used to determine the new value stored

    > into
    > >p, as you explained, but it is _also_ read to determine at which

    > memory
    > >location the second assignment will happen, so it is not _only_ read

    > to
    > >determine the value stored, therefore undefined behavior.

    >
    > There is something wrong. The first assignment is "p->next = q" and
    > "p" is _not_ modified. After this assignment value of "p" is _not_
    > changed; only "p->next" is changed. The second assignemnt is "p =
    > p->next =q" and "p" is going to hold the result of "p->next = q",
    > which is "q".
    >
    > Consider "b = b * 10". According to your logic it will be undefined
    > since b is read to determine new value but also read to determine
    > memory for second assignment.


    Where is the "second assignment" ?
    Christian Bau, Jan 17, 2005
    #3
  4. On Mon, 17 Jan 2005 05:16:19 +0000, Chris Torek wrote:

    ....

    >>After this assignment value of "p" is _not_ changed; only "p->next"
    >>is changed. The second assignemnt is "p = p->next =q " and "p" is
    >>going to hold the result of "p->next = q", which is "q".

    >
    > Yes. The problem comes about because (or "if", depending on how
    > you read the precise text of the C89 and C99 standards) the words
    > "before" and "after" are not applicable. There are those who
    > claim that a C compiler can treat:
    >
    > a = b = c;
    >
    > as if it read:
    >
    > temp = c;
    > a = temp;
    > b = temp;
    >
    > i.e., assign to the leftmost object, then assign to the middle
    > object.


    I was just looking back at this, and IMHO it isn't quite as simple as that.
    I would represent it as the following with & indicating "lvalue of" and *
    "object designated by"

    temp1 = c; /* Evaluation of operand c */
    tempb = &b; /* Evaluation of operand b */
    tempa = &a; /* Evaluation of operand a */
    temp2 = temp1; /* Result of b = c */
    *tempa = temp2; /* Execution of assignment to a */
    *tempb = temp1; /* Execution of assignment to b */

    I have no problem with *tempa = temp2 preceding *tempb = temp1. What I
    don't accept is that *tempa = temp2 can precede tempb = &b, because
    temp2 = temp1 cannot. Essentially you cannot execute an operator in the
    abstract machine before you have evaluated its operands.

    Lawrence
    Lawrence Kirby, Feb 3, 2005
    #4
    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. nagy
    Replies:
    36
    Views:
    1,007
    Terry Reedy
    Jul 20, 2006
  2. Ike Naar

    tricky assignment statemenent

    Ike Naar, Dec 31, 2004, in forum: C Programming
    Replies:
    22
    Views:
    668
    Jun Woong
    Jan 15, 2005
  3. ccwork

    tricky assignment statemenent

    ccwork, Jan 7, 2005, in forum: C Programming
    Replies:
    6
    Views:
    310
    Jun Woong
    Jan 12, 2005
  4. Replies:
    9
    Views:
    534
    CBFalconer
    Apr 25, 2006
  5. Chris
    Replies:
    34
    Views:
    1,515
Loading...

Share This Page