question about "++"

M

mdh

Given the expression:

while (isaspace(c = *s++))
x+1;
(s is an array)

Does the increment to 's' occur after "x+1" is evaluated, or after
the content of s is assigned to c? Is there a general rule as to when
this type of increment occurs? ( I understand that the increment in "c
= ++*s" occurs immediately before assignment, so my guess is the same
would apply in the "after" scenerio, but not sure).

thank you.
 
R

Richard Heathfield

mdh said:
Given the expression:

while (isaspace(c = *s++))
x+1;
(s is an array)

Does the increment to 's' occur after "x+1" is evaluated,

No, before.
or after
the content of s is assigned to c?

Maybe.

Here is one possible ordering:

(1) assign *s to c
(2) increment s

Here's another:

(1) assign *s to a temp
(2) increment s
(3) assign the temp to c

Here's another:

(1) increment s
(2) assign *(s - 1) to c

In any event, all is definitely done and dusted before x+1 happens.

Between one sequence point and the next, the compiler has considerable
freedom with regard to what it does when. (Across sequence points, it
has rather less freedom - it can only mess about if a strictly
conforming program can't tell that it has done so.)
 
M

mdh

mdh said:>
> while (isaspace(c = *s++))

No, before.


Maybe.

Here is one possible ordering:



thank you Richard. That explains a "bug" I had with s incrementing
before I wanted it to.
 
O

Old Wolf

Given the expression:

while (isaspace(c = *s++))
x+1;
(s is an array)

If s is an array then this code has a constraint
violation, as arrays cannot be incremented.

Did you mean (*s)++ ?
 
R

Richard Heathfield

Old Wolf said:
If s is an array then this code has a constraint
violation, as arrays cannot be incremented.

Did you mean (*s)++ ?

At a guess, he meant that s points to an element within an array.
 
O

Old Wolf

Old Wolf said:


At a guess, he meant that s points to an element within an array.

Perhaps; but in the original post he gave the
preincrement version as ++*s (not *++s).
 
N

newbee1984

Perhaps; but in the original post he gave the
preincrement version as ++*s (not *++s).

i think he want to say the increment of 's' occurs before assignment
*s,that's *++s
 
R

Richard Heathfield

mdh said:
Good guess :)

Beware. *s++ and (*s)++ mean different things.

int zog[2] = { 6, 42 };
int *s;

s = zog; *s++ = 12;
/* zog is now { 12, 42 }, *s = 42 */

s = zog; (*s)++;
/* zog is now { 13, 42 }, *s = 13 */

s = zog; *++s;
/* zog is now { 13, 42 }, *s is 42 */

s = zog; ++*s;
/* zog is now { 14, 42 }, *s is 14 */
 
M

mdh

Beware. *s++ and (*s)++ mean different things.

int zog[2] = { 6, 42 };
int *s;

s = zog; *s++ = 12;
/* zog is now { 12, 42 }, *s = 42 */


At the risk of showing total ignorance...( except by now I suppose a
lot of people who answer my queries are used to this !!! :))

So, s is initialized to point at the address of zog[0]. On the face of
it, 12 is assigned to zog[0], then the pointer is incremented by one
and dereferenced. This makes sense, but then I looked at P53 of K&R
and am confused. If I read this correctly, the assignment should occur
last, as it is the lowest order of precedence. Then if * and ++ are
of equal precedence ( line 2, same page) and the associativity is
right to left, why am I incorrect ( and I must be ) in saying that *s+
+ = 12 should first increment the pointer, then dereference it, then
assign 12 to that index, and give zog { 6, 12} /** wrong **/ but why?
I will leave the others for now, as I am sure the answer to this will
help with those examples.

Thank you as usual.
 
C

Chris Dollin

mdh said:
Beware. *s++ and (*s)++ mean different things.

int zog[2] = { 6, 42 };
int *s;

s = zog; *s++ = 12;
/* zog is now { 12, 42 }, *s = 42 */

At the risk of showing total ignorance...( except by now I suppose a
lot of people who answer my queries are used to this !!! :))

So, s is initialized to point at the address of zog[0].
Yes.

On the face of it, 12 is assigned to zog[0],

Yes, via `s`.
then the pointer is incremented by one and dereferenced.

No. The deference happens as part of the assignment; the increment
happens sometime between the beginning of the statement and the
end.
This makes sense, but then I looked at P53 of K&R
and am confused. If I read this correctly, the assignment should occur
last, as it is the lowest order of precedence.

Be warned. /Precedence/ and /order of evaluation/ are not the
same thing. Precedence says what things are operands of what
operators; order of evaluation says what orders of things happening
are allowable.

In `*s++ = 12`, the order of the assignment and the incrementing
/is not specified/; either can happen before the other.
Then if * and ++ are of equal precedence ( line 2, same page)
and the associativity is right to left, why am I incorrect ( and
I must be ) in saying that *s++ = 12 should first increment the
pointer, then dereference it,

The binding in `*s++` is `*(s++)`. The thing that is dereferenced
is the /value of `s++`/, which is the /original/, unincremented,
value of `s`. Contrast with `++s`, which yeilds the /incremented/
value of `s`.

Note that the increment of `s` doesn't have to take place immediately,
either. It's legal to evaluate `*s++ = 12` as

*s = 12; s += 1

if we can ignore the value of the expression.
 
M

mdh

same thing. Precedence says what things are operands of what
operators; order of evaluation says what orders of things happening
are allowable.


Aha...so are you saying that the table on page 53 ( Table 2-1) has
nothing to do with the order of evaluation? ( You say this is
essentially undefined?) Could you please clarify what the term
"associativity" then means?
 
C

Chris Dollin

mdh said:
Aha...so are you saying that the table on page 53 ( Table 2-1) has
nothing to do with the order of evaluation?

My copy of K&R II is at home, but if it's the "usual" table of
precedences, yes.
( You say this is essentially undefined?)

Unspecified. ("Undefined" has a specific meaning here; "all bets
are off, anything could happen, demons could fly out of your nose";
the latter is a Bad Thing even if you have a very heavy cold.)

There are some exceptions: && || ?: and ,-operator have defined
order-of-evaluation rules.

And typically an expression `L op R` can't be evaluated without
first evaluating `L` and `R`. (Exceptions again: || and &&, which
may not need to evaluate `R` at all, and `X ? Y : Z`, which will
evaluate `X` first then exactly one of `Y` or `Z`.)
Could you please clarify what the term
"associativity" then means?

When precedence won't tell you what the operands are, associativity
will. In `A + B + C` it says that it's structured as `(A + B) + C`;
stuff groups to the left.

--
"He could not weigh up which was worse and so tried not to think about either."
/The Spellgrinder's Apprentice/

Hewlett-Packard Limited registered office: Cain Road, Bracknell,
registered no: 690597 England Berks RG12 1HN
 
M

mdh

Be warned. /Precedence/ and /order of evaluation/ are not the
Meaning that things that will happen will be as expected,( versus
undefined) except that "my" anticipated order ( with exceptions you
mentioned) can not be relied upon?

.........

So it sounds like "associativity" and "binding" is synonymous?

So, may I try and summarize what you have told me?

Precedence "asscociates" an operand with an operator ( unary
operator), or 2 operands with and operator. This is very different
from evaluating an expression. (I looked for a definition of
evaluation, and did not find one, but I suppose conceptually it is the
act of "resolving"? an expression.) What you have said is that with
exceptions, the language does not specify an order in which this is to
occur..and I guess, one has to be careful in crafting code to be
unambiguous, in this regard.

So, to go back where this all started:
int zog[2] = { 6, 42 };
int *s;
s = zog; *s++ = 12;
/* zog is now { 12, 42 }, *s = 42 */
The deference happens as part of the assignment; the increment
happens sometime between the beginning of the statement and the
end.

means: ( (*(s++)) = 12 ); /** in terms of precedence **/

Now...I hope I don't get you pulling your hair out ....but...does the
's++' imply that s will only increment AFTER something has happened to
it, which in this case is to have the '12' assigned to that which it
points at, now it is incremented, then it is dereferenced? I think
that I am still a little fuzzy as to the exact meaning of
"evaluation" and "precedence/assocition"..or it may just be too damn
late/early in the morning? :) In other words, is 's++' an evaluation
or an 'association'? Is it obvious to you what I am perhaps missing?
 
C

Chris Dollin

mdh said:
Be warned. /Precedence/ and /order of evaluation/ are not the

Meaning that things that will happen will be as expected,( versus
undefined) except that "my" anticipated order ( with exceptions you
mentioned) can not be relied upon?

It means that the Standard doesn't say what order things happen
in (except when it does), and programs that try to find out risk
falling into Undefined Behaviour.

........

So it sounds like "associativity" and "binding" is synonymous?

Associativity is a way of describing how to get the binding (of
operands to operators).

Note that the Standard doesn't talk about precedence and doesn't
talk about associativity: it just has grammar rules. They Are In
Charge.
Precedence "asscociates" an operand with an operator ( unary
operator), or 2 operands with and operator. This is very different
from evaluating an expression. (I looked for a definition of
evaluation, and did not find one, but I suppose conceptually it is the
act of "resolving"? an expression.) What you have said is that with
exceptions, the language does not specify an order in which this is to
occur..and I guess, one has to be careful in crafting code to be
unambiguous, in this regard.

Unambiguous or indifferent.
So, to go back where this all started:
int zog[2] = { 6, 42 };
int *s;
s = zog; *s++ = 12;
/* zog is now { 12, 42 }, *s = 42 */
means: ( (*(s++)) = 12 ); /** in terms of precedence **/

Now...I hope I don't get you pulling your hair out ....but...does the
's++' imply that s will only increment AFTER something has happened to
it,

No.

It's an expression whose result is the original value of `s`. At
some point (here, sometime before the semicolon; the Standard talks
in terms of "sequence points" which cover those && and ?: etc cases)
`s` will be incremented. That may happen before, after, or during the
delivery of `s`s original value.
which in this case is to have the '12' assigned to that which it
points at, now it is incremented, then it is dereferenced?

Well, really `s` isn't dereferenced; it's original value is. It's
because `s` may be incremented any time before the `;` that you
have to be very careful about the language you use.
I think
that I am still a little fuzzy as to the exact meaning of
"evaluation" and "precedence/assocition"..or it may just be too damn
late/early in the morning? :) In other words, is 's++' an evaluation
or an 'association'? Is it obvious to you what I am perhaps missing?

`s++` is an expression; it has operator `postfix ++` and operand
`variable s`. To evaluate it, deliver the value `s` had before the
(entire) expression was evaluated and arrange for `s` to be incremented
by the time the (entire) expression has finished evaluating.

--
"Go not to the Drazi for counsel, Unsaid /Babylon 5/
for they will answer both 'green' and 'purple'."

Hewlett-Packard Limited Cain Road, Bracknell, registered no:
registered office: Berks RG12 1HN 690597 England
 
R

Richard Heathfield

mdh said:
Beware. *s++ and (*s)++ mean different things.

int zog[2] = { 6, 42 };
int *s;

s = zog; *s++ = 12;
/* zog is now { 12, 42 }, *s = 42 */


At the risk of showing total ignorance...( except by now I suppose a
lot of people who answer my queries are used to this !!! :))

So, s is initialized to point at the address of zog[0]. On the face of
it, 12 is assigned to zog[0], then the pointer is incremented by one
and dereferenced.

No. As a result of *s++ = 12; there are two changes to the values stored
in objects:

* The object zog[0] gets the new value 12
* The object s gets the new value &zog[1]

The order in which these values are given is unspecified.
 
R

Richard

Richard Heathfield said:
mdh said:
Beware. *s++ and (*s)++ mean different things.

int zog[2] = { 6, 42 };
int *s;

s = zog; *s++ = 12;
/* zog is now { 12, 42 }, *s = 42 */


At the risk of showing total ignorance...( except by now I suppose a
lot of people who answer my queries are used to this !!! :))

So, s is initialized to point at the address of zog[0]. On the face of
it, 12 is assigned to zog[0], then the pointer is incremented by one
and dereferenced.

No. As a result of *s++ = 12; there are two changes to the values stored
in objects:

* The object zog[0] gets the new value 12
* The object s gets the new value &zog[1]

The order in which these values are given is unspecified.

In the context if single threaded programs dont you think this is
slightly unnecessary complication?

It is playing with the english language.

It is perfectly "normal" so say

"the value 12 is stored at the address held in s, s is then incremented
to point to the next element"

Its why "++" is called increment,

Yes, I know what you are saying, I fail, however, to see the reason why
in the context of a beginner learning post increment and
reference/dereference.
 
R

Richard Heathfield

Richard said:
Richard Heathfield said:
mdh said:
So, s is initialized to point at the address of zog[0]. On the face
of it, 12 is assigned to zog[0], then the pointer is incremented by
one and dereferenced.

No. As a result of *s++ = 12; there are two changes to the values
stored in objects:

* The object zog[0] gets the new value 12
* The object s gets the new value &zog[1]

The order in which these values are given is unspecified.

In the context if single threaded programs dont you think this is
slightly unnecessary complication?

Not at all. Getting "order of evaluation", "precedence", and
"associativity" separated out is a key step in the journey from
accident to design.
It is playing with the english language.

It is perfectly "normal" so say

"the value 12 is stored at the address held in s, s is then
incremented to point to the next element"

Yes, and that's (roughly) how I'd choose to say it, were it not for the
fact that it is *misleading*, given that this is the very point about
which the O.P. is confused and seeks clarification.
Its why "++" is called increment,

Yes, I know what you are saying, I fail, however, to see the reason
why in the context of a beginner learning post increment and
reference/dereference.

The fact that you fail to see a reason for something does not mean that
no reason exists.
 
B

Ben Bacarisse

mdh said:
Beware. *s++ and (*s)++ mean different things.

int zog[2] = { 6, 42 };
int *s;

s = zog; *s++ = 12;
/* zog is now { 12, 42 }, *s = 42 */


At the risk of showing total ignorance...( except by now I suppose a
lot of people who answer my queries are used to this !!! :))

So, s is initialized to point at the address of zog[0]. On the face of
it, 12 is assigned to zog[0], then the pointer is incremented by one
and dereferenced.

At the risk of labouring the point, imagine executing a C program on a
computer consisting of room full of people. The C standard states
that we can only be sure of what has and has not happened at certain
points. These are the "sequence points" you may have heard about and
we may only open the door of the room at these sequence points.

The program starts:

int zog[2] = { 6, 42 };

We open the door (the ; is a sequence point) and we see two people
standing in a row called zog[0] and zog[1]. They have 6 and 42 pounds
in their pockets respectively. We close the door.

s = zog;

We open it, and see a person, s, pointing at zog[0]. We close the
door.

*s++ = 12;

Upon opening the door we know that the person s was pointing at when
we last looked will now have 12 pounds in his/her pocket, and that s
will now be pointing at the next person in the zog line (zog[1]).
*s++ means "the person s was pointing at (oh, and make sure you are
pointing at their neighbour when we next get to look)".

You are not allowed to know, or even care, exactly what happened in
the room while you were not looking. Did the 12 pounds go into the
pocket before, after, or during s's arm movement? You can't tell and
you should not care.

The *reason* the standard is like this, is to allow compilers (which
issue much more detailed instructions to the people in the room) a
lot of flexibility so they can arrange thing as efficiently as
possible. The compiler might have told s to give zog[0] an extra six
pounds while moving her arm -- no assignment of 12 and no absolute
ordering of the events either.
 
B

Bart van Ingen Schenau

mdh said:
Be warned. /Precedence/ and /order of evaluation/ are not the

Meaning that things that will happen will be as expected,( versus
undefined) except that "my" anticipated order ( with exceptions you
mentioned) can not be relied upon?

No.
Meaning that the compiler can use any order it likes, as long as the
correct operands are used for each operator.
........

So it sounds like "associativity" and "binding" is synonymous?

So, may I try and summarize what you have told me?

Precedence "asscociates" an operand with an operator ( unary
operator), or 2 operands with and operator.

Almost.
The combination of precedence and associativity can tell you (in most
cases) which operands an operator works on.
Basically, precedence and associativity tell you how to create a fully
parenthesised expression that is equivalent to the original expression.

As an example, we take the expression
*s++ = 12
Precedence tells us that = has low precedence, and ++ and * have the
same, higher, precedence. This leads to the parenthesised form
(*s++) = 12
Because * and ++ have the same precedence, we can't use that to place
further parentheses. Now associativity comes into play. The
associativity of these operators is 'right to left', so that is the
order in which we should place our next parentheses:
(*(s++)) = 12
Now it is clear that the * operates on the result of the expression s++.
This is very different
from evaluating an expression. (I looked for a definition of
evaluation, and did not find one, but I suppose conceptually it is the
act of "resolving"? an expression.) What you have said is that with
exceptions, the language does not specify an order in which this is to
occur..and I guess, one has to be careful in crafting code to be
unambiguous, in this regard.

Or even better, write code that does not care about the order of
evaluation.
So, to go back where this all started:
int zog[2] = { 6, 42 };
int *s;
s = zog; *s++ = 12;
/* zog is now { 12, 42 }, *s = 42 */
The deference happens as part of the assignment; the increment
happens sometime between the beginning of the statement and the
end.

means: ( (*(s++)) = 12 ); /** in terms of precedence **/

In terms of the combination of precedence and associativity. (or more
correct: in terms of the language grammar).
Now...I hope I don't get you pulling your hair out ....but...does the
's++' imply that s will only increment AFTER something has happened to
it, which in this case is to have the '12' assigned to that which it
points at, now it is incremented, then it is dereferenced?

Not exactly.
You can interpret 's++' best as: Schedule an increment of s and continue
working with the old value.
In the same way, ++s can be read as: Schedule an increment of s and
continue working with the new value.

For a well-formed program, it does not matter when the compiler finally
gets around to perform the scheduled increment.
I think
that I am still a little fuzzy as to the exact meaning of
"evaluation" and "precedence/assocition"..or it may just be too damn
late/early in the morning? :) In other words, is 's++' an evaluation
or an 'association'? Is it obvious to you what I am perhaps missing?

I would call it both.
To me, association is the process of determining which operands an
operator works on, so the operator++ is associated with the operand s.
Evaluation is more a runtime thing, where the actual calculation is
performed.

Bart v Ingen Schenau
 

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
474,431
Messages
2,571,679
Members
48,796
Latest member
Greg L.

Latest Threads

Top