# 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

2. ### Martin AmbuhlGuest

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

3. ### Keith ThompsonGuest

"" <> 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
4. ### jgGuest

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
5. ### Richard HeathfieldGuest

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
6. ### Malcolm McLeanGuest

"" <> 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
7. ### Chris DollinGuest

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
8. ### peteGuest

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
9. ### Richard HeathfieldGuest

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
10. ### Eric SosmanGuest

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
11. ### Eric SosmanGuest

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
12. ### RichardGuest

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
13. ### Richard HeathfieldGuest

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
14. ### Malcolm McLeanGuest

"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
15. ### Old WolfGuest

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
16. ### Eric SosmanGuest

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
17. ### Harald van D kGuest

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