ProgrammingC Developer, Embedded Engineer

What are lvalue and rvalue in C language, how to distinguish them and what is the practical significance of this distinction?

Pass interviews with Hintsage AI assistant

Answer.

Historically, in the C language, the distinction between lvalue and rvalue arose as a basis for determining to which expressions the assignment operator can be applied. Lvalue (left value) refers to an object that occupies a specific location in memory and to which the address-of operation (&) can be applied. Rvalue (right value) is a temporary value that does not have a specific address. This distinction is important for understanding how assignment works, how arguments are passed to functions, and how the compiler performs optimizations.

The problem arises when attempting to perform operations that are only valid on lvalues (e.g., assignment) on rvalues, and vice versa. This can lead to compilation errors or subtle bugs during execution.

The solution lies in a clear understanding of the contexts in which lvalues and rvalues are used. Example:

int x = 5; int y; y = x; // x is both lvalue and rvalue, y is lvalue y = x + 1; // x + 1 is rvalue (cannot take address) // &x is correct, &(x + 1) is an error

Key features:

  • Lvalue has an address in memory and can be the left operand of an assignment.
  • Rvalue is a temporary value that does not have its own address.
  • Some expressions can be both lvalue and rvalue depending on the context.

Tricky Questions.

Can you take the address of any expression, such as (x + y)?

No, only lvalues have an address. For example, the expression (x + y) is an rvalue.

int z = 3, y = 7; int *p = &(z + y); // Compilation error

What happens if you attempt to assign a value to a constant (e.g., 5 = x)?

A compilation error will occur because the literal 5 is an rvalue and cannot serve as an lvalue.

5 = x; // Error: left operand is not an lvalue

Can a function return an lvalue?

A regular function returns an rvalue, but if a reference is returned (for example, in C++), then it is an lvalue. In C, only rvalue returns are allowed.

int foo() { int x = 5; return x; } // Returns an rvalue

Typical Mistakes and Anti-Patterns

  • Using the address-of operator on expressions that are not lvalues.
  • Attempting to assign to an rvalue, for example, a literal or the result of an arithmetic expression.
  • Expecting that all expressions have an address in memory.

Real-Life Example

Negative Case

A programmer attempted to take the address of a temporary result of the expression (a + b):

int *p = &(a + b);

Pros:

  • A compilation error will immediately indicate the problem.

Cons:

  • A violation of program logic, if the distinction between lvalue and rvalue is not understood, will lead to long searches and unclear errors.

Positive Case

A programmer consciously separates lvalue and rvalue. They use values only where the syntax and semantics allow:

int x = 7; int *p = &x; // correct

Pros:

  • The program works predictably and portably.

Cons:

  • Some minor overhead time on learning the distinction.