The result of ++ is not an lvalue?

Discussion in 'C Programming' started by lovecreatesbea...@gmail.com, May 20, 2007.

  1. Guest

    K&R2, both sec A7.3.4 Postfix Incrementation and secA.7.4.1 Prefix
    Incrementation Operators say that "The result is not an lvalue". Is
    this correct? I don't see an errata on these points. If below the p++
    or ++p is not an lvalue, then *p++ or *++p is a syntax error.

    When it talks about Unary Operators, why doesn't the secA7.4 collect
    both the prefix and postfix incrementation operators together?

    int main(void)
    {
    char a[10] = {0}, *p = a;

    /* a[0] = 'a'; a[1] = 'b'; */
    /* *p = 'a'; *(p+1) = 'b'; */
    /* *p = 'a'; *p++ = 'b'; p--; */
    *p = 'a'; *++p = 'b'; p--;
    return 0;
    }
    , May 20, 2007
    #1
    1. Advertising

  2. wrote:
    > K&R2, both sec A7.3.4 Postfix Incrementation and secA.7.4.1 Prefix
    > Incrementation Operators say that "The result is not an lvalue". Is
    > this correct?


    Yes. The result is a value, and specifies nothing about where it is.
    An lvalue must have a location associated with it.

    > I don't see an errata on these points.


    Errata are reserved for errors. Why should there be an erratum for
    something not in error?

    > If below the p++
    > or ++p is not an lvalue, then *p++ or *++p is a syntax error.


    Really? Why would you claim that?
    When p is a pointer, the result of p++ or ++p is a pointer value which
    can of course be dereferenced. Why would you think that only lvalues
    can be dereferenced? The '*' indirection operator is applied to
    expressions, not just lvalues.

    > When it talks about Unary Operators, why doesn't the secA7.4 collect
    > both the prefix and postfix incrementation operators together?


    The choice of presentation is up to the authors. We are not mind
    readers nor responsible for their choices. Ask them. I'm not even sure
    what your question means. Certainly in K&R1 (A.7.2 Unary Operators) the
    ++lvalue, lvalue--, lvalue++, and lvalue-- are about as close to each
    other as is physically possible.

    >
    > int main(void)
    > {
    > char a[10] = {0}, *p = a;
    >
    > /* a[0] = 'a'; a[1] = 'b'; */
    > /* *p = 'a'; *(p+1) = 'b'; */
    > /* *p = 'a'; *p++ = 'b'; p--; */
    > *p = 'a'; *++p = 'b'; p--;
    > return 0;
    > }
    >
    Martin Ambuhl, May 20, 2007
    #2
    1. Advertising

  3. "" <> writes:
    > K&R2, both sec A7.3.4 Postfix Incrementation and secA.7.4.1 Prefix
    > Incrementation Operators say that "The result is not an lvalue". Is
    > this correct?


    Absolutely.

    > I don't see an errata on these points. If below the p++
    > or ++p is not an lvalue, then *p++ or *++p is a syntax error.


    No, the operand of the unary "*" operator doesn't need to be an
    lvalue; it just needs to be a pointer value.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, May 20, 2007
    #3
  4. jg Guest

    On May 19, 10:48 pm, ""
    <> wrote:
    > K&R2, both sec A7.3.4 Postfix Incrementation and secA.7.4.1 Prefix
    > Incrementation Operators say that "The result is not an lvalue". Is
    > this correct? I don't see an errata on these points. If below the p++


    Yes, the result is not an lvalue.

    > or ++p is not an lvalue, then *p++ or *++p is a syntax error.
    >


    No. That (p++) isn't an lvalue means that there is no way to
    change (p++), and doesn't mean (p++) cannot be dereferenced.

    Let's see p = 1, (p++) is also 1. This '1' cannot be changed
    in the way that any variable is changed because this '1' does not
    have lvalue. You can't do (p++) = 2, for example.
    jg, May 20, 2007
    #4
  5. Keith Thompson said:

    <snip>

    > No, the operand of the unary "*" operator doesn't need to be an
    > lvalue; it just needs to be a pointer value.


    ....which must be of object or function type, and which must actually
    point to an object or function.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
    Richard Heathfield, May 20, 2007
    #5
  6. "" <> wrote in message
    news:...
    > K&R2, both sec A7.3.4 Postfix Incrementation and secA.7.4.1 Prefix
    > Incrementation Operators say that "The result is not an lvalue". Is
    > this correct? I don't see an errata on these points. If below the p++
    > or ++p is not an lvalue, then *p++ or *++p is a syntax error.
    >
    > When it talks about Unary Operators, why doesn't the secA7.4 collect
    > both the prefix and postfix incrementation operators together?
    >
    > int main(void)
    > {
    > char a[10] = {0}, *p = a;
    >
    > /* a[0] = 'a'; a[1] = 'b'; */
    > /* *p = 'a'; *(p+1) = 'b'; */
    > /* *p = 'a'; *p++ = 'b'; p--; */
    > *p = 'a'; *++p = 'b'; p--;
    > return 0;
    > }
    >

    The postfix operators are bit unsusal in that they have high binding
    precedence but are applied last.
    This allows for concise code in loops

    while(*ptr++);

    will step through a zero-terminated array, for instance, setting ptr to the
    position after the last member.

    What this means is that *ptr++ = 0;
    sets *ptr to 0, then increments ptr.

    However my thinking is moving away from this type of code. Generally now I
    put an increment / decrement on its own line. If you've got to think about
    how precedence resolves, the code is unnecessarily hard to read.
    --
    Free games and programming goodies.
    http://www.personal.leeds.ac.uk/~bgy1mm
    Malcolm McLean, May 20, 2007
    #6
  7. Chris Dollin Guest

    Malcolm McLean wrote:

    (fx:snip)

    > This allows for concise code in loops
    >
    > while(*ptr++);
    >
    > will step through a zero-terminated array, for instance, setting ptr to
    > the position after the last member.
    >
    > What this means is that *ptr++ = 0;
    > sets *ptr to 0, then increments ptr.
    >
    > However my thinking is moving away from this type of code. Generally now I
    > put an increment / decrement on its own line. If you've got to think about
    > how precedence resolves, the code is unnecessarily hard to read.


    Or you haven't learnt the idioms.

    `*p++` is a C idiom, widely used. You should no more need to
    think about how precedence resolves to use it than you should
    in `a + b * c`.

    [ie, you have to learn it /sometime/, but once learnt, it's
    like riding a bicycle -- balancing becomes natural, and you
    should always wear a helment in case of accide.]

    --
    Oops I Did It Hedgehog
    "Never ask that question!" Ambassador Kosh, /Babylon 5/
    Chris Dollin, May 20, 2007
    #7
  8. pete Guest

    wrote:

    > If below the p++
    > or ++p is not an lvalue, then *p++ or *++p is a syntax error.


    Wrong.

    There is no requirment for the operand of unary *,
    to be an lvalue.

    Example:
    (p[0]) means the exact same thing as (*(p + 0)).
    (p + 0) is not an lvalue.
    You can't have ((p + 0) = 0).

    --
    pete
    pete, May 20, 2007
    #8
  9. Malcolm McLean said:

    <snip>

    > What this means is that *ptr++ = 0;
    > sets *ptr to 0, then increments ptr.


    No, it doesn't. ++ has higher precedence, and so it is the value of
    ptr++ that is provided as the operand to *. Of course, the value of
    ptr++ is the value that ptr had at the previous sequence point.

    The precise order in which stuff happens is up to the implementation, of
    course, but the Standard requires the semantics of the expression to be
    as I have described.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
    Richard Heathfield, May 20, 2007
    #9
  10. Eric Sosman Guest

    wrote:
    > K&R2, both sec A7.3.4 Postfix Incrementation and secA.7.4.1 Prefix
    > Incrementation Operators say that "The result is not an lvalue". Is
    > this correct? I don't see an errata on these points. If below the p++
    > or ++p is not an lvalue, then *p++ or *++p is a syntax error.


    No. *(any_valid_pointer_expression) is an lvalue, whatever
    the status of any_valid_pointer_expression itself.

    Even if it were an error, it wouldn't be a syntax error.
    There is nothing syntactically wrong with ++TheAnswer = 43;
    the semantics are what doom it.

    > When it talks about Unary Operators, why doesn't the secA7.4 collect
    > both the prefix and postfix incrementation operators together?


    You'd need to ask K or R for their exact reasons, but it
    seems plausible that they separated the postfix operators from
    the prefix operators because the postfix operators are not in
    the same class and have a higher precedence. Oddly enough,
    the Standard makes the same separation.

    --
    Eric Sosman
    lid
    Eric Sosman, May 20, 2007
    #10
  11. Eric Sosman Guest

    Malcolm McLean wrote:
    >
    > The postfix operators are bit unsusal in that they have high binding
    > precedence but are applied last.


    This is complete nonsense.

    > This allows for concise code in loops
    >
    > while(*ptr++);
    >
    > will step through a zero-terminated array, for instance, setting ptr to
    > the position after the last member.
    >
    > What this means is that *ptr++ = 0;
    > sets *ptr to 0, then increments ptr.


    Wrong again. The time when ptr is incremented is not
    specified; indeed, the incrementation may take "macroscopic
    time" and overlap with other operations bracketed by the
    same pair of sequence points. Regardless of the scheduling
    of the increment, though, the value of ptr++ is defined
    as the value of ptr as it was before the ++ operator caused
    any change. That value is what the * operator uses, and
    the lvalue produced by * is what the = operator uses. Neither
    the = nor the * use the "current" value of ptr in any way.

    > However my thinking is moving away from this type of code. Generally now
    > I put an increment / decrement on its own line. If you've got to think
    > about how precedence resolves, the code is unnecessarily hard to read.


    The third sentence is true, but if "you've got to think"
    about precedence when reading something as simple as *p++, it
    means your ability to read C has not yet transcended the level
    of "LOOK, JANE. SEE SPOT. SEE SPOT RUN."

    --
    Eric Sosman
    lid
    Eric Sosman, May 20, 2007
    #11
  12. Richard Guest

    Richard Heathfield <> writes:

    > Malcolm McLean said:
    >
    > <snip>
    >
    >> What this means is that *ptr++ = 0;
    >> sets *ptr to 0, then increments ptr.

    >
    > No, it doesn't. ++ has higher precedence, and so it is the value of
    > ptr++ that is provided as the operand to *. Of course, the value of
    > ptr++ is the value that ptr had at the previous sequence point.


    What?

    Are you really telling me that the most famous string copy in the world
    doesn't work im comp.lang.c land?

    while(*dest++=*src++);

    or you making life difficult for human beings again?

    His text above is pretty clear and makes sense.

    *ptr is indeed set to 0 and then (in terms of this sentence) ptr is
    incremented.

    Or?!?!?! Am I losing my senses?
    Richard, May 21, 2007
    #12
  13. Richard said:

    > Richard Heathfield <> writes:
    >
    >> Malcolm McLean said:
    >>
    >> <snip>
    >>
    >>> What this means is that *ptr++ = 0;
    >>> sets *ptr to 0, then increments ptr.

    >>
    >> No, it doesn't. ++ has higher precedence, and so it is the value of
    >> ptr++ that is provided as the operand to *. Of course, the value of
    >> ptr++ is the value that ptr had at the previous sequence point.

    >
    > What?
    >
    > Are you really telling me that the most famous string copy in the
    > world doesn't work im comp.lang.c land?
    >
    > while(*dest++=*src++);


    Not at all. If you think so, you have misinterpreted what I wrote.

    > or you making life difficult for human beings again?


    Not at all. I'm actually trying to make life /easier/, by making clear
    what the Standard actually guarantees about the expression *ptr++ = 0;

    > His text above is pretty clear and makes sense.


    Sure. It's just wrong, that's all, although this isn't quite as clear
    from the quoted text alone as from the article in which it was
    originally said:

    "The postfix operators are bit unsusal in that they have high binding
    precedence but are applied last."

    That was the viewpoint he was trying to explain, and that viewpoint is
    incorrect.

    > *ptr is indeed set to 0 and then (in terms of this sentence) ptr is
    > incremented.


    That isn't guaranteed by the Standard. For example, the following
    pseudo-assembly-language would be a perfectly legal translation:

    MOV tmp, ptr
    INC ptr
    MOV *tmp, 0

    In other words, the increment can happen first, and the update
    afterwards. Whether this actually happens depends on the implementor.
    The Standard certainly permits it.

    > Or?!?!?! Am I losing my senses?


    I couldn't possibly comment.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
    Richard Heathfield, May 21, 2007
    #13
  14. "Richard Heathfield" <> wrote in message
    news:...
    > Richard said:
    >
    >> Richard Heathfield <> writes:
    >>
    >>> Malcolm McLean said:
    >>>
    >>> <snip>
    >>>
    >>>> What this means is that *ptr++ = 0;
    >>>> sets *ptr to 0, then increments ptr.
    >>>
    >>> No, it doesn't. ++ has higher precedence, and so it is the value of
    >>> ptr++ that is provided as the operand to *. Of course, the value of
    >>> ptr++ is the value that ptr had at the previous sequence point.

    >>
    >> What?
    >>
    >> Are you really telling me that the most famous string copy in the
    >> world doesn't work im comp.lang.c land?
    >>
    >> while(*dest++=*src++);

    >
    > Not at all. If you think so, you have misinterpreted what I wrote.
    >
    >> or you making life difficult for human beings again?

    >
    > Not at all. I'm actually trying to make life /easier/, by making clear
    > what the Standard actually guarantees about the expression *ptr++ = 0;
    >
    >> His text above is pretty clear and makes sense.

    >
    > Sure. It's just wrong, that's all, although this isn't quite as clear
    > from the quoted text alone as from the article in which it was
    > originally said:
    >
    > "The postfix operators are bit unsusal in that they have high binding
    > precedence but are applied last."
    >
    > That was the viewpoint he was trying to explain, and that viewpoint is
    > incorrect.
    >

    Explain. Not define.

    --
    Free games and programming goodies.
    http://www.personal.leeds.ac.uk/~bgy1mm
    Malcolm McLean, May 21, 2007
    #14
  15. Old Wolf Guest

    On May 21, 2:18 am, Eric Sosman <> wrote:
    >
    > No. *(any_valid_pointer_expression) is an lvalue, whatever
    > the status of any_valid_pointer_expression itself.


    Except when it doesn't designate an object (e.g. if
    the any_valid_pointer_expression is pointing one off
    the end of an array).
    Old Wolf, May 21, 2007
    #15
  16. Eric Sosman Guest

    Old Wolf wrote On 05/21/07 17:31,:
    > On May 21, 2:18 am, Eric Sosman <> wrote:
    >
    >> No. *(any_valid_pointer_expression) is an lvalue, whatever
    >>the status of any_valid_pointer_expression itself.

    >
    >
    > Except when it doesn't designate an object (e.g. if
    > the any_valid_pointer_expression is pointing one off
    > the end of an array).


    One thing about c.l.c. is that verbal shortcuts always
    catch up with one ... I used "valid" suggestively rather
    than precisely, and dangitall if'n somebody didn't call me
    on it.

    Another way a perfectly good pointer value can fail to
    be "valid" in my imprecise sense is to be a pointer to an
    incomplete type, e.g., a `void*' or a `struct opaque*'.
    Such a pointer can be perfectly well-defined, useful, and
    a model citizen in every way, yet not be capable of yielding
    an lvalue.

    And if somebody nit-picks that `struct opaque' might
    not be an incomplete type, I'm gonna boot up my DS9K and
    do some DAMAGE!

    http://dialspace.dial.pipex.com/town/green/gfd34/art/

    --
    Eric Sosman, May 21, 2007
    #16
  17. Old Wolf wrote:
    > On May 21, 2:18 am, Eric Sosman <> wrote:
    > >
    > > No. *(any_valid_pointer_expression) is an lvalue, whatever
    > > the status of any_valid_pointer_expression itself.

    >
    > Except when it doesn't designate an object (e.g. if
    > the any_valid_pointer_expression is pointing one off
    > the end of an array).


    Even then, and rightly so. Just imagine, otherwise whether

    static void inc(int *p) {
    ++*p;
    }

    is a constraint violation (remember, a diagnostic is required for
    constraint violations) depends on what values of p will be passed to
    it at runtime.
    Harald van D k, May 21, 2007
    #17
    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. Kavya
    Replies:
    9
    Views:
    493
    Dik T. Winter
    Oct 28, 2006
  2. Replies:
    11
    Views:
    682
    James Kuyper
    Sep 22, 2008
  3. J.Ram
    Replies:
    7
    Views:
    639
  4. Michael Tan
    Replies:
    32
    Views:
    927
    Ara.T.Howard
    Jul 21, 2005
  5. Julian Mehnle
    Replies:
    0
    Views:
    227
    Julian Mehnle
    Jul 17, 2003
Loading...

Share This Page