3

I've heard the terms lvalue and rvalue come up when working with pointers.
However, I don't fully understand their meaning.

What are lvalues and rvalues?

Note 1: This is a question about C's lvalues and rvalues, not C++'s. It's also about their functionality, not their naming.

Note 2: I already fully understand these concepts. This is meant as a canonical duplicate target.

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
  • section 6.3.2.1 of the C11 standard draft covers this. – Christian Gibbons Aug 29 '19 at 19:58
  • @dandan78 That's a C++ question. – S.S. Anne Aug 29 '19 at 20:00
  • @ChristianGibbons I know. I was meaning for this to be a canonical dupe target. – S.S. Anne Aug 29 '19 at 20:01
  • Of possible help is [Please clarify the concept of lvalue and rvalue here](https://stackoverflow.com/questions/38983284/please-clarify-the-concept-of-lvalue-and-rvalue-here). – Weather Vane Aug 29 '19 at 20:05
  • @WeatherVane Still not what I'm trying to accomplish. I want this to be generic. – S.S. Anne Aug 29 '19 at 20:06
  • 1
    @JL2210 I had a sneaking suspicion that may have been the case, but figured it wouldn't hurt to throw that out anyways. – Christian Gibbons Aug 29 '19 at 20:06
  • There are no rvalues in C / the term is not used. – Antti Haapala -- Слава Україні Aug 29 '19 at 20:09
  • @AnttiHaapala Then what's `&var`? – S.S. Anne Aug 29 '19 at 20:09
  • @JL2210 Never would've guessed since I see way too many similar questions that could've been answered with 30 seconds of googling. Anyhow, even though it's almost certainly not the best choice of dupe target, it is also tagged as C and does go into what they are. – dandan78 Aug 29 '19 at 20:09
  • 2
    @AnttiHaapala It's odd that section 6.3.2.1 doesn't ever use the term 'rvalue', but in the index of the C11 standard draft, the term 'rvalue' does come up, and points you to that section. EDIT: actually, footnote 64 does make reference to "rvalue" – Christian Gibbons Aug 29 '19 at 20:12
  • 1
    @ChristianGibbons it's a footnoote: *The name "lvalue" comes originally from the assignment expression E1 = E2, in which the left operand E1 is required to be a (modifiable) lvalue. It is perhaps better considered as representing an object "locator value". What is sometimes called "rvalue"" is in this International Standard described as the "value of an expression".* – Weather Vane Aug 29 '19 at 20:15
  • @ChristianGibbons Sorry, you edited the comment as I was posting. I wonder why they decided to use "value of an expression" in the document and not "rvalue", but used the term "lvalue" rather than "locator value". – Weather Vane Aug 29 '19 at 20:19
  • 2
    the "rvalue" is a nonsense category in that all lvalues, if they designate an object, can undergo lvalue conversion and become "rvalues". – Antti Haapala -- Слава Україні Aug 29 '19 at 20:27

2 Answers2

4

I've got a longer answer here, but basically C11 draft n1570 6.3.2.1p1:

An lvalue is an expression (with an object type other than void) that potentially designates an object [...]

C11 n1570 Footnote 64:

64) The name lvalue comes originally from the assignment expression E1 = E2, in which the left operand E1 is required to be a (modifiable) lvalue. It is perhaps better considered as representing an object locator value. What is sometimes called rvalue is in this International Standard described as the value of an expression. An obvious example of an lvalue is an identifier of an object. As a further example, if E is a unary expression that is a pointer to an object, *E is an lvalue that designates the object to which E points.

Not all lvalues are modifiable, i.e. can appear on the left side of an assignment. Examples of unmodifiable lvalues are those that

  • have array type,
  • have incomplete type
  • are const-qualified
  • structs or unions that have const-qualified members either directly or recursively

An lvalue can be converted to a value of an expression through lvalue conversion. I.e. in

int a = 0, b = 1;
a = b;

both a and b are lvalues, as they both potentially - and actually - designate objects, but b undergoes lvalue conversion on the right-hand side of the assignment, and the value of the expression b after lvalue conversion is 1.

"Potentially designating an object" means that given int *p;, *p designates an object of type int iff p points to an object of type int - but *p is an lvalue even if p == NULL or indeterminate.

1

According to the C Reference Manual (3rd Edition):

An lvalue is an expression that refers to an object in such a way that the object may be examined or altered. Only an lvalue expression may be used on the left-hand side of an assignment. An expression that is not an lvalue is sometimes called an rvalue because it can only appear on the right-hand side of an assignment. An lvalue can have an incomplete array type, but not void.

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
daShier
  • 2,056
  • 2
  • 8
  • 14
  • Can you give some background other than just copying from some "C reference manual"? – S.S. Anne Aug 29 '19 at 23:27
  • I figured there were lots of comments giving personal explanations. I elected to quote an accepted text. – daShier Aug 30 '19 at 00:05
  • 1
    I think the C standard is more accepted than some non-standardized manual. Could you at least provide a link to the material? – S.S. Anne Aug 30 '19 at 00:08
  • @JL2210 The text I referenced above is: __C: A Reference Manual 3th Edition_ by Samuel P. Harbison and Steele Jr., Guy L. Published by Prentice Hall. A search on Amazon shows it's now in its 5th Edition. – daShier Aug 30 '19 at 21:32