What is an lvalue?
相关问题
- What do we call the combined path, query, and frag
- “Scraping” vs. “Scrapping”: Is there a difference?
- What is the correct term for _ in a type hint?
- CSS media query operators
- What is the correct terminology of XML's eleme
相关文章
- What does “exposition only” mean? Why use it?
- “Adapter” or “adaptor”?
- What is {{$guid}} used for in Postman?
- What is a bit field in layman's terms?
- CSS pseudo-class vs. pseudo-selector
- What does “CL” mean in a commit message? What does
- Does the implementation of pow() function in C/C++
- Model-driven development: What is a transform?
An lvalue is a value that can be assigned to:
It's short for "left value" or "lefthand value" and it's basically just the value on the left of the
=
sign, i.e. the value you assign something to.As an example of what is not an lvalue (i.e rvalue only):
That code doesn't work because
printf()
(a function that returns anint
) cannot be an lvalue, only an rvalue.From this article. Since the OP was a bit lazy in asking his question (although some people disagree, see comments), I'll be lazy as well and simply paste the entire relevant part here, probably breaking some copyright laws.
For the C programming language C11 draft n1570 6.3.2.1p1 puts it succinctly:
It is as simple as that.
The Wikipedia definition on the day of writing this answer was almost as good
Examples of lvalue expressions? Given
we can have the following lvalue expressions:
a
,b
andc
each of which definitely designate an object.b[0]
designates an object as well, hence it is an lvalue expression. What about the potentiality then?*c
is always an lvalue expression, but it does not designate an object ifc
does not hold a pointer to a valid object.b[1]
could semantically designate an object but it doesn't because it accesses the array out of bounds. Both of them are lvalue expressions.When an lvalue expression that does not actually designate an object is evaluated, the behaviour is undefined.
An lvalue expression can be more complex than that, for example:
if it compiles, it is an lvalue expression.
Basically everything that you can apply the
&
(address-of operator) to in C is an lvalue, except functions, since functions are not objects in C.So what does the L then stand for?
C11 n1570 Footnote 64:
Notice that
E1 = E2
is not required to compile forE1
to be an lvalue in ISO C. 6.3.2.1p1 continues:It used to be case in languages before C (for example B) that all locator values could appear on the left-hand side of the assignment, hence the naming. This is no longer the case in C since arrays could never have been assigned to, and ISO C added
const
.P.S. The same footnote explains the related term rvalue like this:
It's traditionally the left side of the "=" operator. However, with time, meaning of "lvalue"/"rvalue" changed. C++ added the term of a "non-modifiable lvalue" which is any lvalue that cannot assigned to: arrays and variables that are qualified with "const" are two examples. In C, you cannot assign to any rvalue (see below). Likewise, in C++, you cannot assign to rvalues that are not of some user defined class type.
You can say an "lvalue" is an expression that names an object which persists over time and occupies some location of storage. Whether or not you can assign to that expression is not important for that classification. A reference, in particular, is also an lvalue, because it has a name that persists over time. All the following are lvalues, because they all refer to named objects. Also note that a
const
does not have any effect on the lvalue-ness.The term "rvalue" is used for things like literals and enumerator values and for temporaries that do not enjoy the fun of having a long life and are destroyed right away at the end of a full expression. For rvalues, not the aspect of persistence is important, but the value-aspect. Functions in C++ are lvalues, because they are persistent and they have an address, even though they are not objects. I've left them out in the above overview of lvalues, because it's easier to grasp lvalues when first only taking objects into account. All the following are rvalues:
Incidentally, often you have an lvalue, but an operator needs an rvalue. For example the binary builtin "+" operator adds two values. An lvalue expression first and for all specifies a location where a value first has to be read out. So when you add two variables, an "lvalue to rvalue" conversion takes place. The Standard says that the value contained in an lvalue expression is its rvalue result:
Other operators do not take rvalue, but lvalues. They don't read a value. An example is the address-of operator,
&
. You cannot take the address of an rvalue expressions. Some rvalues are not even objects: They do not occupy any storage. Examples are again, literals (10, 3.3, ...) and enumerator values.How is that scary stuff useful?
Well it has several advantages to have the distinction of lvalue and rvalue
... There is more to it, i feel it ...
The "L" in lvalue is usually described as standing for "location". An lvalue specifies the location of something; as another answerer pointed out, lvalues can typically have their address taken. This is why numeric literals and non-reference function return values are not lvalues.
The L used to stand for "left" until const was introduced into C++. Const lvalues cannot appear on the left hand side of an assignment.
Something that appears on the left hand side of an assignment i.e. something that can be assigned to.
Note that in C++ a function call may be an lvalue if:
then: