The result of ++ is not an lvalue?

L

lovecreatesbea...

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;
}
 
M

Martin Ambuhl

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;
}
 
K

Keith Thompson

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.
 
J

jg

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.
 
R

Richard Heathfield

Keith Thompson said:

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.
 
M

Malcolm McLean

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.
 
C

Chris Dollin

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.]
 
P

pete

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).
 
R

Richard Heathfield

Malcolm McLean said:

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.
 
E

Eric Sosman

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.
 
E

Eric Sosman

Malcolm said:
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."
 
R

Richard

Richard Heathfield said:
Malcolm McLean said:



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?
 
R

Richard Heathfield

Richard said:
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.
 
M

Malcolm McLean

Richard Heathfield said:
Richard said:


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


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


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.
 
O

Old Wolf

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).
 
E

Eric Sosman

Old Wolf wrote On 05/21/07 17:31,:
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/
 
H

Harald van D k

Old said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top