I read this sentence in a book: C primer Plus (The sixth edition) Since I read the Chinese version, I can only translate the Chinese version of the book as follows.
Rvalue: refers to a value that can be assigned to a modifiable left value and is not itself an lvalue.
Is this true or false? I feel like there's something wrong with that sentence. My opinion is as follows:
#include <stdio.h>
int main(void) {
int a = 3; ok beacase 3 is constent
int b = 3 + 4; ok beacase 3 is expression
int c = a; ? a is rvalue
/*
a is an rvalue, isn't that inconsistent with what we said before and not an lvalue itself? I hadn't noticed this basic problem before. I wish someone could help me. Ask sb. to do STH.
*/
return 0;
}
a
itself should be an lvalue
. Isn't that so?
I read this sentence in a book: C primer Plus (The sixth edition) Since I read the Chinese version, I can only translate the Chinese version of the book as follows.
Rvalue: refers to a value that can be assigned to a modifiable left value and is not itself an lvalue.
Is this true or false? I feel like there's something wrong with that sentence. My opinion is as follows:
#include <stdio.h>
int main(void) {
int a = 3; ok beacase 3 is constent
int b = 3 + 4; ok beacase 3 is expression
int c = a; ? a is rvalue
/*
a is an rvalue, isn't that inconsistent with what we said before and not an lvalue itself? I hadn't noticed this basic problem before. I wish someone could help me. Ask sb. to do STH.
*/
return 0;
}
a
itself should be an lvalue
. Isn't that so?
Rvalue: refers to a value that can be assigned to a modifiable left value and is not itself an lvalue.
The C standard does not use “rvalue.” This description of the word comes from programming and computer science generally and from the book you used; it is not part of the C standard. The only appearance of “rvalue” in the C 2024 standard is in a footnote mentioning its use outside the C standard: “What is sometimes called ‘rvalue’ is in this document described as the ‘value of an expression’.”
In int c = a;
, a
is an lvalue. However, we cannot assign an lvalue to another object; we can only store a value in an object. a
is, by itself, an expression. When this expression is evaluated, a
is automatically converted to the value stored in a
. C 2024 6.3.3.1 says:
… Except when it is the operand of the
sizeof
operator, or thetypeof
operators, the unary&
operator, the++
operator, the--
operator, or the left operand of the.
operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion…
The way this conversion is performed is, of course, by loading the value of a
from the memory where a
is located. Then, for int c = a;
, c
is initialized with this value.
So the author is technically wrong to say a
is an rvalue. In int c = a;
, a
is an lvalue, but the result of evaluating a
is an rvalue (in the sense of being a value that is not an lvalue).
Rvalue: refers to a value that can be assigned to a modifiable left value and is not itself an lvalue.
Is this true or false? I feel like there's something wrong with that sentence.
The idea conveyed by the English sentence presented is accurate, though the wording is awkward. However, you seem to have taken the incorrect idea from it that only rvalues can appear as the right-hand operand of an assignment operation. Perhaps you're ignoring the "and is not itself an lvalue" part? That's by far the more important criterion.
int c = a; ? a is rvalue /* a is an rvalue, isn't that inconsistent with what we said before and not an lvalue itself? I hadn't noticed this basic problem
before. I wish someone could help me. Ask sb. to do STH. */
a
is an lvalue because it designates an object. Objects have associated storage. It is not an rvalue, because, as your definition specifically says, lvalues are not rvalues.
Although the terms "lvalue" and "rvalue" are derived from the idea of what kinds of expressions can appear on the left and right sides of an assignment, that really doesn't get to the core idea:
An lvalue expression is one that (potentially) designates an object, as I said above. A variable name, an array subscription expression (array[1]
), a structure or union member selection (s.member
), and a pointer derference (*p
) are all examples.
An rvalue, on the other hand, is an expression that is not an lvalue. Such an expression does not designate an object, only a value. Some would insist that it not be a void
expression. Such a value is ephemeral in that it exists only in the context of the full expression in which it appears. Integer and floating constants; arithmetic, relational, sizeof
, and alignof
expressions; and function return values are among the common kinds of rvalues in C.
Any expression of suitable data type may appear as the right-hand operand of an assignment. That doesn't speak to whether the expression is an lvalue or an rvalue.
rvalue and lvalue is not a property of the symbol itself, but is part of the C language syntax, and so, where it appears in an expression. An rvalue is a value whose value is used only to provide data to do some calculation, and so, it can only appear in the right part of an assignment, or as part of the expression that produces a vaue. An lvalue on the contrary, can appear in both sides of an assignment, but it must provide storage available because some value will be stored there. The terms lvalue (left value) and rvalue( right value) come from the side of the assignment operator =
they come from. The syntax for an assignment in C is something like:
<assignment> ::= <lvalue> '=' <rvalue>.
The problem gets a bit more complex as an lvalue can be also the result of a complex operation. So, for example:
r[5+a]
is an lvalue, as it refers to the cell of an array whose position is a+5
(where a+5
is taken as an rvalue to use its value only) It can be used in the left side of an assignment (to assing a value to that cell of the array) and as an rvalue in the following case:
b = r[5+a];
An lvalue can always be used as an rvalue, but the opposite is not true, for example, you cannot say:
5+a = r[3]; /* ERROR ERROR ERROR */
(you cannot assign the contents of the array cell at position 3
to the value 5+a
)
The thing can become more complex, as for example:
f(3)->first = 64;
in this case, f(3)
is a function that returns a pointer to a structure with a field first
(which is essentially a storage) and can be assigned a value. so, the expression f(3)->first
is an lvalue (and also a possible rvalue)
&
can be applied to it. In your case&a
is perfectly fine, soa
is an lvalue. If you had something likeint c = function(a);
thena
is still an lvalue, but the result offunction(a)
is an rvalue. – Some programmer dude Commented Jan 2 at 14:29a
is definitely an lvalue. – wohlstad Commented Jan 2 at 14:34&
can be applied to it.”:x
is an lvalue given the definitionregister int x;
, but&
cannot be applied to it.s.x
is also an lvalue givenstructure { int x : 3; } s;
, but&
cannot be applied to it. A function name is not an lvalue, but&
can be applied to it. – Eric Postpischil Commented Jan 2 at 15:01