I run into a about rvalue concept problem in C Programming Language - Stack Overflow

admin2025-05-01  0

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?

Share Improve this question edited Jan 2 at 14:50 earearlength asked Jan 2 at 14:24 earearlengthearearlength 113 bronze badges 5
  • 3 The simple quick test if something is an lvalue or a rvalue, is to check if the pointer-to operator & can be applied to it. In your case &a is perfectly fine, so a is an lvalue. If you had something like int c = function(a); then a is still an lvalue, but the result of function(a) is an rvalue. – Some programmer dude Commented Jan 2 at 14:29
  • 1 a is definitely an lvalue. – wohlstad Commented Jan 2 at 14:34
  • 1 Whenever you ask a question about something in a book or document, give a complete bibliographic citation for it, the way you were taught in school. Cite the author, the title, the edition, the year of publication, the page and/or chapter, section, clause, and paragraph numbers, any other information useful for identifying the document, and, if it is available online, a URL. Among other things, this helps readers locate context that may help explain the statement. – Eric Postpischil Commented Jan 2 at 14:56
  • 2 @Someprogrammerdude: Re “The simple quick test if something is an lvalue or a rvalue, is to check if the pointer-to operator & can be applied to it.”: x is an lvalue given the definition register int x;, but & cannot be applied to it. s.x is also an lvalue given structure { 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
  • @EricPostpischil I know I phrased it a little too simple perhaps. – Some programmer dude Commented Jan 2 at 15:04
Add a comment  | 

3 Answers 3

Reset to default 5

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 the typeof 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)

转载请注明原文地址:http://anycun.com/QandA/1746114901a91875.html