postfix (prefix) increment, L-value and R-value (i

2019-02-14 01:07发布

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

2条回答
Bombasti
2楼-- · 2019-02-14 02:07

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)
查看更多
看我几分像从前
3楼-- · 2019-02-14 02:13

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 its consequences if it was accepted by the compiler

{

int i = 0;

int* pi = &(i++); // Not OK !! because virtually 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; // the post increment happening only after the assignment !!!

I hope this help clarifying a bit ;)

查看更多
登录 后发表回答