postfix vs prefix operator

S

subramanian100in

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
 
V

Victor Bazarov

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
 
J

Jerry Coffin

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

subramanian100in

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

Jerry Coffin

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

Jerry Coffin

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

James Kanze

On Jun 24, 12:06 am, Jerry Coffin <[email protected]> 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.
 
J

Jon Harrop

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

renjumc

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


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


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

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,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top