Velocity Reviews > C++ > postfix vs prefix operator

# postfix vs prefix operator

subramanian100in@yahoo.com, India
Guest
Posts: n/a

 06-23-2007
Consider

int i = 10;

Why do we say that ++i yields an Lvalue and i++ yields an Rvalue ?

I thought both these expressions yield only values.

I am unable to understand the difference

Kindly explain.

Thanks
V.Subramanian

Victor Bazarov
Guest
Posts: n/a

 06-23-2007
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> Consider
>
> int i = 10;
>
> Why do we say that ++i yields an Lvalue and i++ yields an Rvalue ?

Because they do. Why do we say that water is wet?

> I thought both these expressions yield only values.

That would be incorrect. There are no such thing as "only values".

> I am unable to understand the difference

You can take an address of an lvalue, you can initialise a reference
to-non-const with it, you can apply another increment to it...

int i = 10;
int *pi = &(++i);// OK
int &ri = ++i; // OK
++i--; // OK

You can't do those things with an r-value:

int i = 10;
int *pi = &(i++);// NOT OK
int &ri = i++; // NOT OK
i++--; // NOT OK

What book are you reading that doesn't explain that?

V
--

Jerry Coffin
Guest
Posts: n/a

 06-23-2007
In article <(E-Mail Removed). com>,
(E-Mail Removed) says...
> Consider
>
> int i = 10;
>
> Why do we say that ++i yields an Lvalue and i++ yields an Rvalue ?
>
> I thought both these expressions yield only values.
>
> I am unable to understand the difference

From the looks of it, when you say "only values", you basically mean
"rvalues".

An rvalue is only a value -- something like zero. It doesn't necessarily
have any storage associated with it.

An lvalue is a variable or something along that general line -- a piece
of storage that holds some value at any given time.

As the difference between pre- and post-increment, the reason for the
difference is fairly simple. In the case of pre-increment, you increment
the variable, and the result IS that variable. In the case of post-
increment, we increment the variable, but the result is the value the
variable held _before_ the increment -- so the result canNOT be held in
that variable. This means the result _has_ to be the value independent
of the variable -- so we no longer have the address of a variable, and
instead have only the value itself.

--
Later,
Jerry.

The universe is a figment of its own imagination.

subramanian100in@yahoo.com, India
Guest
Posts: n/a

 06-24-2007
On Jun 24, 12:06 am, Jerry Coffin <(E-Mail Removed)> wrote:

Thanks Jerry Coffin.

Kindly clarify the following doubt also related to the Lvalue.

Consider the following code:

int main()
{
int x = 100;

++x = 1000;

return 0;
}

If I create a C source file containing this code and compile it under
both VC++2005 express edition and also gcc under Linux, I am getting
compilation error for the assignment:
++x = 1000;
error being invalid Lvalue in assignment.

However if I create a C++ source file containing this code and compile
it under VC++ 2005 and also g++, I do not get any compilation error.

Questions:
----------
1) Does it mean that prefix operator in C does not produce Lvalue in C
unlike C++ ?

2) I read that, in C++ postfix increment and decrement operator have
higher precedence than the prefix operator. But in C they have the
same precedence. Am I right or wrong ?

Kindly explain.

Jerry Coffin
Guest
Posts: n/a

 06-24-2007
In article <(E-Mail Removed). com>,
(E-Mail Removed) says...

[ ... ]

> 1) Does it mean that prefix operator in C does not produce Lvalue in C
> unlike C++ ?

That's correct -- in C 6.5.16/3 specifies that: " An assignment
expression hs the value of the left operand after the assignment, but is
not an lvalue."

6.5.16.2/3 says: "A compound assignment of the form E1 op= E2 differs
from the simple assignment E1 = E1 op (E2) only in thta the lvalue E1 is
evaluated only once."

Finally, 6.5.3.1/2 says: "The expression ++E is equivalent to (E+=1)."
and 6.5.3.1/3 says: "The prefix -- operator is analogous to the prefix
++ operator, except that the value of the operand is decremented."

So, in C a prefix increment or decrement does no produce an lvalue.

> 2) I read that, in C++ postfix increment and decrement operator have
> higher precedence than the prefix operator. But in C they have the
> same precedence. Am I right or wrong ?

You're not exactly right, but not completely wrong either. Neither the C
nor C++ standard specifies precedence directly -- in both cases, the
precedence must be deduced from the grammar.

In both cases, the grammar specifies postfix operators with higher
precedence than prefix. In reality, however, this doesn't really matter
much -- the only time the relative precedence of a prefix and postfix
operator matters is if both are being applied to the same operand, such
as "++a++;".

In C, since the operators never produce lvalues, and the operand of the
prefix operator needs to be an lvalue, you can never have an expression
where both the pre- and post-fix operators are applied to the same
operand -- so there's never a conflict between the two that you need to
resolve via precedence.

In C++, for built-in types, the situation is the same. A user-defined
type, however, can overload the operators and return modifiable lvalues
in both cases:

For example:

#include <iostream>

class X {
int x;
public:
X(int init = 0) : x(init) {}

int &operator++() { return ++x; }
int &operator++(int) { return ++x; }

operator int() { return x; }
};

int main() {
X x;

++x++;
std::cout << x;

return 0;
}

#include <iostream>

class X {
int x;
public:
X(int init = 0) : x(init) {}

int &operator++() { return ++x; }

// well-formed but truly evil code:
int &operator++(int) { return ++x; }

operator int() { return x; }
};

int main() {
X x;

// also well-formed:
++x++;
std::cout << (int) x;

return 0;
}

Now, the difference in precedence is meaningful. We're applying both
operators to the same operand, and the higher effective precedence of
the postfix operator means the "++x++" is equivalent to:

x.operator++(int).operator++();

rather than:

x.operator++().operator++(int);

For built-in types, the postfix operators do not produce modifiable
lvalues, so an expression like this is ill-formed, and the difference in
precedence is a moot point, just like in C.

--
Later,
Jerry.

The universe is a figment of its own imagination.

Jerry Coffin
Guest
Posts: n/a

 06-24-2007
In article <(E-Mail Removed). com>,
(E-Mail Removed) says...

[ ... ]

> 1) Does it mean that prefix operator in C does not produce Lvalue in C
> unlike C++ ?

That's correct -- in C 6.5.16/3 specifies that: " An assignment
expression hs the value of the left operand after the assignment, but is
not an lvalue."

6.5.16.2/3 says: "A compound assignment of the form E1 op= E2 differs
from the simple assignment E1 = E1 op (E2) only in thta the lvalue E1 is
evaluated only once."

Finally, 6.5.3.1/2 says: "The expression ++E is equivalent to (E+=1)."
and 6.5.3.1/3 says: "The prefix -- operator is analogous to the prefix
++ operator, except that the value of the operand is decremented."

So, in C a prefix increment or decrement does no produce an lvalue.

> 2) I read that, in C++ postfix increment and decrement operator have
> higher precedence than the prefix operator. But in C they have the
> same precedence. Am I right or wrong ?

You're not exactly right, but not completely wrong either. Neither the C
nor C++ standard specifies precedence directly -- in both cases, the
precedence must be deduced from the grammar.

In both cases, the grammar specifies postfix operators with higher
precedence than prefix. In reality, however, this doesn't really matter
much -- the only time the relative precedence of a prefix and postfix
operator matters is if both are being applied to the same operand, such
as "++a++;".

In C, since the operators never produce lvalues, and the operand of the
prefix operator needs to be an lvalue, you can never have an expression
where both the pre- and post-fix operators are applied to the same
operand -- so there's never a conflict between the two that you need to
resolve via precedence.

In C++, for built-in types, the situation is the same. A user-defined
type, however, can overload the operators and return modifiable lvalues
in both cases:

For example:

#include <iostream>

class X {
int x;
public:
X(int init = 0) : x(init) {}

int &operator++() { return ++x; }
int &operator++(int) { return ++x; }

operator int() { return x; }
};

int main() {
X x;

++x++;
std::cout << x;

return 0;
}

#include <iostream>

class X {
int x;
public:
X(int init = 0) : x(init) {}

int &operator++() { return ++x; }

// well-formed but truly evil code:
int &operator++(int) { return ++x; }

operator int() { return x; }
};

int main() {
X x;

// also well-formed:
++x++;
std::cout << (int) x;

return 0;
}

Now, the difference in precedence is meaningful. We're applying both
operators to the same operand, and the higher effective precedence of
the postfix operator means the "++x++" is equivalent to:

x.operator++(int).operator++();

rather than:

x.operator++().operator++(int);

For built-in types, the postfix operators do not produce modifiable
lvalues, so an expression like this is ill-formed, and the difference in
precedence is moot, just like in C.

--
Later,
Jerry.

The universe is a figment of its own imagination.

James Kanze
Guest
Posts: n/a

 06-24-2007
On Jun 24, 5:12 am, "(E-Mail Removed), India"
<(E-Mail Removed)> wrote:
> On Jun 24, 12:06 am, Jerry Coffin <(E-Mail Removed)> wrote:

> Kindly clarify the following doubt also related to the Lvalue.

> Consider the following code:

> int main()
> {
> int x = 100;
> ++x = 1000;
> return 0;
> }

> If I create a C source file containing this code and compile it under
> both VC++2005 express edition and also gcc under Linux, I am getting
> compilation error for the assignment:
> ++x = 1000;
> error being invalid Lvalue in assignment.

> However if I create a C++ source file containing this code and compile
> it under VC++ 2005 and also g++, I do not get any compilation error.

Jerry has explained most of this, including the fact that this
is a difference between C and C++. I would add, however, that
in C++ the expression "++x = 1000" has undefined behavior,
because you are modifying the variable x twice without an
intervening sequence point.

--
James Kanze (Gabi Software) email: (E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jon Harrop
Guest
Posts: n/a

 06-26-2007
(E-Mail Removed), India wrote:
> Consider
>
> int i = 10;
>
> Why do we say that ++i yields an Lvalue and i++ yields an Rvalue ?
>
> I thought both these expressions yield only values.
>
> I am unable to understand the difference

There is no logical reason for these choices. Just avoid all non-trivial
parts of the C++ language. Or avoid the whole language...

--
Dr Jon D Harrop, Flying Frog Consultancy
The OCaml Journal
http://www.ffconsultancy.com/product...ournal/?usenet

renjumc@gmail.com
Guest
Posts: n/a

 07-18-2007
On Jun 23, 8:22 am, "Victor Bazarov" <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:
> > Consider

>
> > int i = 10;

>
> > Why do we say that ++i yields an Lvalue and i++ yields an Rvalue ?

>
> Because they do. Why do we say that water is wet?
>
> > I thought both these expressions yield only values.

>
> That would be incorrect. There are no such thing as "only values".
>
> > I am unable to understand the difference

>
> You can take an address of an lvalue, you can initialise a reference
> to-non-const with it, you can apply another increment to it...
>
> int i = 10;
> int *pi = &(++i);// OK
> int &ri = ++i; // OK
> ++i--; // OK
>

> You can't do those things with an r-value:
>
> int i = 10;
> int *pi = &(i++);// NOT OK
> int &ri = i++; // NOT OK
> i++--; // NOT OK
>
> What book are you reading that doesn't explain that?
>
> V
> --

dear victor

d statement ++i--; // OK
is not a valid one.. if u compile dis it will show "++ needs
Lvalue....
its because the postfix operator has high precedence than a prefix
operator.. so i-- will be done before ++i..
so it can be written as (++i)--;// OK ...