Reputation: 110572
There's a pretty extensive description of lvalue in What are rvalues, lvalues, xvalues, glvalues, and prvalues?, but this is geared towards c++ and I think a lot of those are not applicable to C.
My understanding of an Lvalue would be as follows:
Arrays are not, but their subscript values may be, as long as those are not an array. For example:
int arr[3][2];
arr // no --> int[3][2]
arr[1] // no --> int[2]
arr[1][1] // yes --> int
Structs can be directly or through member access, such as .
or ->
, as long as they don't evaluate to an array. For example:
struct Member {int id};
Member member = {.id=2}, *member_ptr = &member;
member = {.id=3}; // ok
member_ptr = &member; // ok
member.id=3; // ok
member_ptr->id=4; // ok
The address-of &
operator can not. For example:
a = 7;
b = &a;
&b = &a; // invalid
The value-of *
operator can be as long as it doesn't refer to an array.
int x[2][2] = {{1,2}, {3,4}};
*(x+1)=3; // not ok, evaluates to x[2]
*(*(x+1)+1) = 3; // ok
Other than more obvious cases such as doing 7=x
, are there main items that I'm missing in my understanding? Or any items that are incorrect in the above?
Upvotes: 0
Views: 154
Reputation: 225757
The C standard defines an lvalue in section 6.3.2.1p1 as follows:
An lvalue is an expression (with an object type other than
void
) that potentially designates an object; if an lvalue does not designate an object when it is evaluated, the behavior is undefined. When an object is said to have a particular type, the type is specified by the lvalue used to designate the object. A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a const-qualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a const-qualified type.
This definition includes arrays, however an array is not a modifiable lvalue.
The result of the indirection operator *
is also an lvalue as it refers to an object. This also applies if the resulting object is an array.
The array subscript operator []
also results in an lvalue as x[y]
is exactly equivalent to *(x + y)
.
The result of the member access operator .
and pointer-to-member operator ->
is also an lvalue.
A compound literal is an lvalue as well. For example, the following is valid:
int *p = (int [3]){1,2,3};
p[0] = 4;
Upvotes: 2