0

I was told that the array name is an non-modifiable l-value in C, but it is still confusing.

Someone said that the array name can not be placed on the left side of the formula because it is converted to a pointer that is not l-value.

My question is Here:

  1. is an array name l-value?
  2. Is there any difference between what means l-value in c and c++?
이승훈
  • 43
  • 5
  • Array identifier is an lvalue - both in C and C++. – Igor R. Jul 30 '19 at 16:11
  • For some more information on this question, see [this answer](https://stackoverflow.com/questions/50808782/what-does-impossibility-to-return-arrays-actually-mean-in-c/50808867#50808867) and its comments. (You'll notice, in fact, that the first comment is from the same John Bollinger who has answered your question here. The question of "is an array name an lvalue?" is a complicated one. It's certainly not a modifiable lvalue, and it can't appear on the **l**eft-hand side of an assignment operator, so it's at best a non-modifiable lvalue.) – Steve Summit Jul 30 '19 at 18:29

2 Answers2

1
  1. is an array name l-value?

Yes, in both C and C++.

  1. Is there any difference between what means l-value in c and c++?

Yes, but not of great significance. Here is the definition from C11, paragraph 6.3.2.1/1:

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

C also includes a footnote (#64) expanding on that, which includes:

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''. [...] An obvious example of an lvalue is an identifier of an object.

Here is the definition from C++14, paragraph 3.10/1:

An lvalue (so called, historically, because lvalues could appear on the left-hand side of an assignment expression) designates a function or an object.

If you read carefully, you will notice that in C, an lvalue only potentially designates an object, whereas in C++, no room is left for unfulfilled potential -- an lvalue does designate an object or function. You'll also then notice that C++ includes function designators among its lvalues, whereas C does not. In practice, these distinctions are more technical than deeply meaningful. And neither of them affects the answer to your question (1).

You'll also note that neither definition is written in terms of how or where an lvalue can be used. That follows from the definition and other specifications; it is not a defining characteristic.

In both C and C++, an array's identifier designates an object -- the array -- and it is therefore an lvalue. Whether such an lvalue may in fact appear as the left operand in an assignment expression is an entirely separate question.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Thank you so much. It was helpful. It's a stupid question, but does an array name itself take up space in the memory? – 이승훈 Jul 31 '19 at 07:38
  • @이승훈, the array itself takes up memory, but its identifier is like all other symbols appearing in the program source. C and C++ do not specify whether identifiers take up memory at runtime, and none of their specifications or requirements imply that identifiers are accessible at runtime (unlike Python, Java, and various others). – John Bollinger Jul 31 '19 at 11:52
0

In the context of C:

6.3.2.1 Lvalues, arrays, and function designators

1 An lvalue is an expression (with an object type other than void) that potentially designates an object;64) 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.

2 Except when it is the operand of the sizeof operator, the _Alignof operator, 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. If the lvalue has qualified type, the value has the unqualified version of the type of the lvalue; additionally, if the lvalue has atomic type, the value has the non-atomic version of the type of the lvalue; otherwise, the value has the type of the lvalue. If the lvalue has an incomplete type and does not have array type, the behavior is undefined. If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.

3 Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
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.

C 2011 Online Draft

Summarizing:

An array expression (that is, any expression of array type) is indeed an lvalue; however, unless it is the operand of the sizeof, _Alignof, or unary & operators, that expression gets converted ("decays") to an expression of pointer type whose value is the address of the first element of the array, and that converted pointer expression is not an lvalue, and thus cannot be the target of an assignment.

That is, if you declare a as

T a[N]; // for any type `T`

then the expression a has type "N-element array of T". If a is not the operand of the sizeof, unary &, or _Alignof operators, it will be converted to an expression of type "pointer to T", and its value will be the same as &a[0], and that value cannot be the target of an assignment (it's logically the same as writing 2 = 3 - you're trying to assign a value to a value, not an object, which doesn't work).

Community
  • 1
  • 1
John Bode
  • 119,563
  • 19
  • 122
  • 198