What are value categories in C?

Share

Each expression in C is characterized by two properties: a type and its value category. There are two types of value categories in C, the lvalue and rvalue.

lvalue:

Simply put, lvalue refers to any expression or object that can appear on the left side of the assignment operator.

lvalue is an expression that refers to an objectan area of named storage in C. Therefore, function definitions and names are not lvalues because you cannot assign anything to them.

lvalue operands can be used in the following scenarios:

  • as the left-side operand of the assignment operator
  • as the operand of the & *(address-of) operator
  • as the left side operand of the member access . (dot) operator
  • as the operand of the pre or post-increment/decrement operators

Rvalue:

rvalues refers to anything that can be put on the right side of the assignment operator. To be more specific, rvalues are expressions that do not represent a named storage in memory. This means that you cannot assign any value to them, and you cannot use & with them or modify them in any way. rvalues are often literals or temporary objects that are created during the execution of a program.

Example

Consider the following line of code:

int i = 100;

Here, the expression is assigning the value 100100 to variable i. The variable i is an area in the memory that can be referenced. In other words, we can use the name i to refer to a specific memory location; this is what we call an lvalue.

However, the value 100100 does not hold a named location in the memory, which means we cannot use it to store data or dereference it. For example, the following expression would not make much sense because 100100 does not refer to a memory location. Simply put, we have no way of accessing the memory address of this literal. This literal is an rvalue.

100 = i; //

rvalues are not necessarily always literals; they can be temporary objects that are created when a function returns a value as well. Let’s see an example of temporary objects as rvalues.

Suppose we have a function:

int temp_func()
{
    return 10;
}

We can assign the value returned by the function to a variable like this:

int x = temp_func();

The returned value of the function is stored in the memory in a temporary variable. However, we have no means of accessing that value or its memory location, making the temporary value an rvalue.

As with all rvalues, if we try to assign some value to a function that returns a value, we will get an error.

temp_funct() = 100; // Will give an lvalue error

Generally speaking, it is safe to assume that rvalues appear on the right side and lvalues appear on the left side of an expression. However, the important distinction between them is not where they appear in an expression, but rather their properties as discussed above. For example, an lvalue can also be used on the right side of an expression:

int i = 10;
int j = i;

Here, the variable i is used on the right-hand side of the assignment operator. This does not make i an rvalue just on the basis of where it appears in the expression. It is still an lvalue since the variable i refers to named storage in memory, meaning it can be referenced using the & operator and works with the pre and post-increment and decrement operators.

Copyright ©2024 Educative, Inc. All rights reserved