postfix (prefix) increment, L-value and R-value (in C and C++)
Asked Answered
C

2

6

I just learned the following facts:

  • The result of a prefix increment (++var_name) is an R-value in C (at least, I am sure that it is not a L-value in C), but it is an L-value in C++.

  • The result of a postfix increment (var_name++) is an R-value in C (at least, I am sure that it is not a L-value in C). This is also true in C++ (It says the result is a prvalue).

I checked these in VS2010 (.cpp and .c) and Ubuntu (gcc and g++).

In p.109 (5.3.2) of C++ Standard http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf, it is written

The operand of prefix ++ is modified by adding 1, or set to true if it is bool (this use is deprecated). The operand shall be a modifiable lvalue. The type of the operand shall be an arithmetic type or a pointer to a completely-defined object type. The result is the updated operand; it is an lvalue, and...

and in p.101, (5.2.6)

The value of a postfix ++ expression is the value of its operand. ... The result is a prvalue. The type of the result is the cv-unqualified version of the type of the operand. See also 5.7 and 5.17.

(I don't know the difference between R-value and prvalue though).

As to C standard http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf, prefix ++ is described in 6.5.3.1 and postfix is in 6.5.2.4, but from the description, I can't get a clear, definite answer.

I would like to know the reasons that make them being R-value or L-value. All I know is that

We can assign a value to a (modifiable) L-value, for example, a variable name. R-value is a value of an expression.

But I don't know the details why postfix ++ is not a L-value in C and C++, and why prefix ++ is not in C. (I saw something like "postfix ++...store...in a temporary address, then...", but I still don't get it).

And another question is that why prefix ++ is different in C and C++? Making prefix ++ a L-value (in C++) has many advantages? If so, why C doesn't change this? (Other reasons than backward compatibility, or at least why changing it will cause a lot of problems).

Contextual answered 25/1, 2014 at 14:30 Comment(8)
You said you checked your assumptions in VS2010 and gcc. What code did you use to verify your assumptions about these issues?Schlegel
""(I saw something like "postfix ++...store...in a temporary address, then...", but I still don't get it)"" - Maybe if you quote the whole sentence from the standard that you don't get, someone could clarify it for you.Schlegel
@Brandin, it is not in the standard. I saw it on a book, which says "The expression a++ in the third statement is an rvalue because it stores the value of a temporarily as the result of the expression and then increments a . "Contextual
Also, just using statements like (a++) = 3, (++a) = 3.Contextual
Do those examples produce different results on different C and C++ compilers? I thought your question was about a difference between C and C++.Schlegel
No, the results are just the same as described the standards, in each compiler I tried. My question is about difference between C and C++ as you said, not the compiler.Contextual
That standard (N3242) is pretty old.Discommode
It is in 2011. It's old?Contextual
C
1

C and C++ are different languages. C++ has operator overloading and C does not. The ++ operators, whether prefix or postfix, are operators which can be overloaded in C++. C++ also has references and C does not.

In C, ++i and i++ both yield a value which is not an lvalue. This is desirable, as otherwise you could run afoul with undefined behaviour by trying to modify the same scalar within the same sequence-point boundaries.

Food for thought: In C, the comma operator also produces a value which is not an lvalue, so to "drop" lvalueness, you can do:

(0, lvalue)
Cautionary answered 15/8, 2014 at 0:43 Comment(0)
F
1

It is true that

  • pre increment/decrement operator (++var or --var) yields an lvalue (i.e a modifiable object)

  • post increment/decrement operator (var++ or var--) yields an rvalue (i.e a temporary object).

Consider following code with pre increment/decrement operator

{

int i = 0;

int* pi = &(++i);

}

It´s OK because in fact its pseudo code is

i = i+1; // pre increment i

int* pi = &i; // then evaluate its address and assign it to pi 

Now consider the same code but with post increment/decrement operator and the consequences if this invalid code is accepted by the compiler

{

int i = 0;

int* pi = &(i++); // Not OK !! because it is a temporary variable

}

Its pseudo code would be

int i = 0;

int tmp = i; // compiler creates a temporary variable to save value of i

int* pi = &tmp; // then would take the address of a temporary variable 

i = i + 1; 
Fey answered 4/7, 2017 at 12:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.