Velocity Reviews > is ++n equivalent to (n=n+1) ?

# is ++n equivalent to (n=n+1) ?

Kobu
Guest
Posts: n/a

 02-04-2005
Hi,

I've gotten into the habit of mentally converting big expressions to
parse tress (started doing this after reading some c.l.c posts on parse
trees).

Can someone verify if the following assumptions are correct?

1) For ++n, one can us (n=n+1) as it's equivalent:

| =
| / \
| n +
| / \
| n 1

2) For assignment operators of the form n op= b, the equivalent tree
is:

| =
| / \
| n op
| / \
| n b

3) For n++, one can use n, but with a side condition that (n=n+1) will
occur somewhere between now and the earliest sequence point up the tree
(but n=n+1 is no physically part of the tree)

|
| n
|
| [Side note: (n=n+1) can occure as a side effect anytime before the
| earliest sequence point up the tree]

Are my assumption correct?

Walter Roberson
Guest
Posts: n/a

 02-04-2005
In article <(E-Mail Removed) .com>,
Kobu <(E-Mail Removed)> wrote:
:I've gotten into the habit of mentally converting big expressions to
arse tress

:Can someone verify if the following assumptions are correct?

:1) For ++n, one can us (n=n+1) as it's equivalent:

No. Suppose n is an expression that returns an lvalue and which
has side effects. In n = n + 1 then n will be evaluated for both
sides of the assignment, resulting in the side effect being done
twice. In n++ or n op= p n will only be evaluated once.

--
When your posts are all alone / and a user's on the phone/
there's one place to check -- / Upstream!
When you're in a hurry / and propagation is a worry/
there's a place you can post -- / Upstream!

Christian Bau
Guest
Posts: n/a

 02-04-2005
In article <(E-Mail Removed) .com>,
"Kobu" <(E-Mail Removed)> wrote:

> Hi,
>
> I've gotten into the habit of mentally converting big expressions to
> parse tress (started doing this after reading some c.l.c posts on parse
> trees).
>
> Can someone verify if the following assumptions are correct?
>
> 1) For ++n, one can us (n=n+1) as it's equivalent:
>
> | =
> | / \
> | n +
> | / \
> | n 1
>
>
> 2) For assignment operators of the form n op= b, the equivalent tree
> is:
>
> | =
> | / \
> | n op
> | / \
> | n b

Correct, except that the lvalue n is only evaluated once. So

++(*++p); ++a [i++];

is absolutely not the same as

(*++p) = (*++p) + 1; a [i++] = a [i++] + 1;

but for a plain variable like n it is correct. (2) is quite important if
you need to figure out exactly what happens for example if you have a
complicated case like

unsigned short us;
double d;

us += d;

In a case like that, all you need to do is to read what exactly (us + d)
does, and then you read the rules what assigning a double to an unsigned
short exactly does. Defining it this way must have saved dozens of pages
in the C Standard.

> 3) For n++, one can use n, but with a side condition that (n=n+1) will
> occur somewhere between now and the earliest sequence point up the tree
> (but n=n+1 is no physically part of the tree)
>
> |
> | n
> |
> | [Side note: (n=n+1) can occure as a side effect anytime before the
> | earliest sequence point up the tree]

Yes.

Kobu
Guest
Posts: n/a

 02-05-2005
Christian Bau wrote:
> In article <(E-Mail Removed) .com>,
> "Kobu" <(E-Mail Removed)> wrote:
>
> > Hi,
> >
> > I've gotten into the habit of mentally converting big expressions

to
> > parse tress (started doing this after reading some c.l.c posts on

parse
> > trees).
> >
> > Can someone verify if the following assumptions are correct?
> >
> > 1) For ++n, one can us (n=n+1) as it's equivalent:
> >
> > | =
> > | / \
> > | n +
> > | / \
> > | n 1
> >
> >
> > 2) For assignment operators of the form n op= b, the equivalent

tree
> > is:
> >
> > | =
> > | / \
> > | n op
> > | / \
> > | n b

>
> Correct, except that the lvalue n is only evaluated once. So
>
> ++(*++p); ++a [i++];
>
> is absolutely not the same as
>
> (*++p) = (*++p) + 1; a [i++] = a [i++] + 1;
>
>
> but for a plain variable like n it is correct. (2) is quite important

if
> you need to figure out exactly what happens for example if you have a

> complicated case like
>
> unsigned short us;
> double d;
>
> us += d;
>
> In a case like that, all you need to do is to read what exactly (us +

d)
> does, and then you read the rules what assigning a double to an

unsigned
> short exactly does. Defining it this way must have saved dozens of

pages
> in the C Standard.
>
> > 3) For n++, one can use n, but with a side condition that (n=n+1)

will
> > occur somewhere between now and the earliest sequence point up the

tree
> > (but n=n+1 is no physically part of the tree)
> >
> > |
> > | n
> > |
> > | [Side note: (n=n+1) can occure as a side effect anytime before

the
> > | earliest sequence point up the tree]

>
> Yes.

Good point, I guess I can represent (exp)++ where exp has meaning as
an lvalue as:

| =
| / \
| temp +
| / \
| = 1
| / \
| temp exp <-- exp would really be more branching
| (executed once)

where (exp) = (exp) + 1 would be:

| =
| / \
| exp + <--
| / \ |-- exp related branching in two places
| exp 1 <-- (executed twice)
|

TTroy
Guest
Posts: n/a

 02-05-2005

Kobu wrote:
> Christian Bau wrote:
> > In article <(E-Mail Removed) .com>,
> > "Kobu" <(E-Mail Removed)> wrote:
> >
> > > Hi,
> > >
> > > I've gotten into the habit of mentally converting big expressions

> to
> > > parse tress (started doing this after reading some c.l.c posts on

> parse
> > > trees).
> > >
> > > Can someone verify if the following assumptions are correct?
> > >
> > > 1) For ++n, one can us (n=n+1) as it's equivalent:
> > >
> > > | =
> > > | / \
> > > | n +
> > > | / \
> > > | n 1
> > >
> > >
> > > 2) For assignment operators of the form n op= b, the equivalent

> tree
> > > is:
> > >
> > > | =
> > > | / \
> > > | n op
> > > | / \
> > > | n b

> >
> > Correct, except that the lvalue n is only evaluated once. So
> >
> > ++(*++p); ++a [i++];
> >
> > is absolutely not the same as
> >
> > (*++p) = (*++p) + 1; a [i++] = a [i++] + 1;
> >
> >
> > but for a plain variable like n it is correct. (2) is quite

important
> if
> > you need to figure out exactly what happens for example if you have

a
>
> > complicated case like
> >
> > unsigned short us;
> > double d;
> >
> > us += d;
> >
> > In a case like that, all you need to do is to read what exactly (us

+
> d)
> > does, and then you read the rules what assigning a double to an

> unsigned
> > short exactly does. Defining it this way must have saved dozens of

> pages
> > in the C Standard.

>

snip

>
> Good point, I guess I can represent (exp)++ where exp has meaning

as
> an lvalue as:
>
>
> | =
> | / \
> | temp +
> | / \
> | = 1
> | / \
> | temp exp <-- exp would really be more branching
> | (executed once)
>
>
> where (exp) = (exp) + 1 would be:
>
> | =
> | / \
> | exp + <--
> | / \ |-- exp related branching in two places
> | exp 1 <-- (executed twice)
> |

Does this distinction apply to (exp) op= b ? Is exp guranteed to
evaluate only once or is (exp) op= b truly equivalent to (exp) = (exp)
op b ?

Walter Roberson
Guest
Posts: n/a

 02-05-2005
In article <(E-Mail Removed). com>,
TTroy <(E-Mail Removed)> wrote:
oes this distinction apply to (exp) op= b ? Is exp guranteed to
:evaluate only once or is (exp) op= b truly equivalent to (exp) = (exp)
p b ?

The C89 standard says that they are equivilent -except- that (exp)
is evaluated only once for (exp) op= b .

--
Suppose there was a test you could take that would report whether
you had Free Will or were Pre-Destined. Would you take the test?

TTroy
Guest
Posts: n/a

 02-05-2005

Walter Roberson wrote:
> In article <(E-Mail Removed) .com>,
> Kobu <(E-Mail Removed)> wrote:
>

snipped

>
> No. Suppose n is an expression that returns an lvalue and which
> has side effects. In n = n + 1 then n will be evaluated for both
> sides of the assignment, resulting in the side effect being done
> twice. In n++ or n op= p n will only be evaluated once.
>
>

I've never seen that. A function name followed by the -> operator. Is
this part of C or C++? I thought -> only goes with structures.

>
> --
> When your posts are all alone / and a user's on the phone/
> there's one place to check -- / Upstream!
> When you're in a hurry / and propagation is a worry/
> there's a place you can post -- / Upstream!

Kenneth Brody
Guest
Posts: n/a

 02-05-2005
TTroy wrote:
[...]
> >

>
> I've never seen that. A function name followed by the -> operator. Is
> this part of C or C++? I thought -> only goes with structures.

Hint:

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <(E-Mail Removed)>

Walter Roberson
Guest
Posts: n/a

 02-06-2005
In article <(E-Mail Removed). com>,
TTroy <(E-Mail Removed)> wrote:

:Walter Roberson wrote:

:I've never seen that. A function name followed by the -> operator. Is
:this part of C or C++? I thought -> only goes with structures.

-> goes with pointers to structures. A function can return
a pointer. In traditional C, a function could not return a structure
directly.
--
Any sufficiently advanced bug is indistinguishable from a feature.
-- Rich Kulawiec

CBFalconer
Guest
Posts: n/a

 02-06-2005
Walter Roberson wrote:
> Kobu <(E-Mail Removed)> wrote:
>
>> I've gotten into the habit of mentally converting big expressions
>> to parse tress

>
>> Can someone verify if the following assumptions are correct?

>
>> 1) For ++n, one can us (n=n+1) as it's equivalent:

>
> No. Suppose n is an expression that returns an lvalue and which
> has side effects. In n = n + 1 then n will be evaluated for both
> sides of the assignment, resulting in the side effect being done
> twice. In n++ or n op= p n will only be evaluated once.

That depends on the stupidity level of the code generator. For
example, for n = n+1, we might generate:

(load address of n to r1) only in a STUPID code generator.
store indirect r2 via r1

n has been evaluated only once, and the expression value is in r2.
Now the n++ may be more complex, because of the need to use the
original value. The compiler may detect that this is not needed,
but...

copy r2 to r3
store indirect r2 via r1

now the expression value is in r3. Of course all this depends
highly on the machine language instructions available.

Some of the important things in code generation are selecting
registers, and remembering what is in them, and when you don't
know. The more you can put off selecting, filling, and discarding
registers the better the chance of doing it efficiently by finding
out you can reuse something.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the