What Exactly Is an R-Value in C++

What exactly is an R-Value in C++?

"Could someone explain, or point me to some sort of explanation, of what R-Value is? I'm not really sure what it is"

The term lvalue originally referred to an expression that could be the left hand side of an assignment. Correspondingly, an rvalue (although as I recall that term was not used by the C89 standard), was originally just the opposite: an expression that could not be the left hand side of an assignment, but that could only be the right hand side.

C++11 complicated this by adding several more nuanced terms, but let's concentrate on the C++03 meanings.

For example, if you have

int x;

then the assignment x = 42 is OK, so x is an lvalue expression.

As a counter-example, the assigment x+0 = 42 is not OK, so x+0 is an rvalue expression.

And so is the expression 2+2, it's an rvalue expression.

So, if the requirement is that your program should include an rvalue, then just write 2+2 or e.g. (more advanced) 6*7, in main.

Original C didn't have const. In C++, with const, you have to disregard the const for the purpose of designating an expression as lvalue or rvalue. The critical point is then whether the expression guaranteed refers to an object in memory, an object with an address: if so, then the expression is an lvalue.

A reference type implies lvalue, because an expression of reference type is necessarily referring to an object with a memory address, i.e. that expression is an lvalue.

However, other than references there's no connection between type and lvalue/rvalue. For example, both x and x+0 are expressions of type int, and they yield the same int value. But the former is an lvalue expression, while the latter is an rvalue expression.

As a general rule, if you can apply the built-in address operator, then it's an lvalue expression, and otherwise it's an rvalue expression.

L value vs R value in C

l-values are values that are defined after they are executed (++x)
r-values are values that are not defined after they are executed (x++)

No, that's not correct.

The words "lvalue" and "rvalue" (that's how the C standard spells them) have a long history. The terms come from 'l' for "left" and 'r' for "right", referring to the left and right sides of an assignment.

In some contexts, an expression may be either evaluated for its lvalue or evaluated for its rvalue. Given those definitions of the terms, an "rvalue" is what you'd normally think of as the value of an expression; evaluating 2+2 yields 4. Evaluating an expression for its lvalue meant determining what object it refers to. For example, given:

int x;
x = 2 + 2;

the right side of the assignment, 2 + 2 would be evaluated for its rvalue, yielding 4, and the left side would be evaluated for its lvalue, which means determining the object to which it refers. (The rvalue of the expression is not evaluated; the value previously stored in x, if any, is not used.)

The C standard defines them differently. In C, an lvalue is not a value; it's a kind of expression. Specifically, quoting the 2011 ISO C standard, section 6.3.2.1:

An lvalue is an expression (with an object type other than void) that
potentially designates an object; if an lvalue does not designate an
object when it is evaluated, the behavior is undefined.

(The word "potentially" was added to cover cases like *ptr, where ptr is a pointer object; if ptr == NULL then *ptr doesn't currently designate an object, but it's still an lvalue. You can always determine at compile time whether a given expression is an lvalue or not. Earlier editions of the C standard had flawed definitions for lvalue.)

So basically an lvalue in C is an expression that designates an object. You can think of it as an expression that can appear on the left side of an assignment, though that's not entirely accurate; for example, the name of a const object can't be on the LHS of an assignment, but it's still an lvalue. (As you can see, nailing down a precise and consistent definition for lvalue can be tricky.)

Neither x++ nor ++x is an lvalue in C.

The C standard doesn't use the term rvalue beyond mentioning it in a single footnote:

What is sometimes called "rvalue" is in this International Standard
described as the "value of an expression".

So, as C defines the terms, an lvalue is a kind of expression (something that exists in C source code), but an rvalue is the result of evaluating an expression (something that exists during program execution).

(C++ has different rules, and several other classes of lvalue-like things, including glvalues and so forth. I won't get into that here.)

Please clarify the concept of lvalue and rvalue here

In c the postfix or prefix ++ operators require that the operand is a modifiable lvalue. Both operators perform an lvalue conversion, so the object is no longer an lvalue.

C++ also requires that the operand of the prefix ++ operator is a modifiable lvalue, but the result of the prefix ++ operator is an lvalue. This is not the case for the postfix ++ operator.

Therefore (++(++i)); compiles as the second operation gets an lvalue, but (++(i++)) doesn't.

where is rvalue stored in c?

Typically, the r-value is "stored" within the program itself.

In other words, the compiler itself (before the program is ever run) computes the 10 + 5 - 3 value (it can do so since since it is all based on constant immediate values), and it emits the assembly code to store the result of this calculation in whatever l-value for the assignement (in this case, the variable named a, which the compiler probably knows as a relative address to a data segment origin of sorts).

The r-value, which has a value of 12 is therefore only found inside the binary of the program, within a assembly instruction that looks like

  mov <some dest, typically DS-relative>, $0C 

$0C is the "r-value".

If the r-value happened to be the result of a calculation that can only done at run-time, say if the underlying c code was: a = 17 * x; // x some run time var, the r-value would too be "stored" (or rather materialized) as a series of instructions within the program binary. The difference with the simple "mov dest, imm" above is that it would take several instructions to load the variable x in an accumulator, multiply by 17 and store the result at the address where the variable a is. It is possible that the compiler may "authorize itself" ;-) to use the stack for some intermediate result etc. but such would be

a) completely compiler dependent

b) transiant

c) and typically would only involve part of the r-value

it is therefore safe to say that the r-value is a compile-time concept which is encapsulated in parts of the program (not the data), and isn't stored anywhere but in the program binary.

In response to paxdiablo: the explanation offered above is indeed restrictive of the possibilities because the c standard effectively does not dictate anything of that nature. Never the less, most any r-value is eventually materialized, at least in part, by some instructions which sets things up so that the proper value, whether calculated (at run time) or immediate gets addressed properly.

l-value , r-value in pointer C

An rvalue is just a value -- 17, or 3.14 or something on that order.

An lvalue is (simplifying a bit) something that refers to someplace in memory that can/does hold a value.

The most common lvalue is just a variable, so in something like x=10, x is an lvalue, and 10 is an rvalue. In fact, that's the origin of the names: an lvalue was (originally) anything that could appear on the Left side of an assignment, and an Rvalue was something that could appear on the right side of an assignment.

Converting an lvalue to an rvalue basically just means retrieving the value stored in the lvalue from wherever it's stored (usually memory). There isn't really any normal conversion from an rvalue to an lvalue though -- once you have something like 10, you can't convert back to a memory location. It's just 10 at that point, and the fact that there might be some variable with the value 10 (or more than one) doesn't mean you can convert the 10 back into the variable.



Related Topics



Leave a reply



Submit