Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: Array is an non-modifiable lvalue - where does it matter? Date: Fri, 16 Jul 2021 02:31:18 -0700 Organization: None to speak of Lines: 83 Message-ID: <87eeby38rd.fsf@nosuchdomain.example.com> References: <5c1d96ea-c554-4aa1-b0db-a7729027ee04n@googlegroups.com> <875yxbth6r.fsf@bsb.me.uk> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Injection-Info: reader02.eternal-september.org; posting-host="25c9c1bea30ea2af62c752c5e5bf9013"; logging-data="16442"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/tYGEGRmwgNwkhRL1fwNab" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) Cancel-Lock: sha1:rKTmpBbTvQeb+abS71CLsMafDGQ= sha1:Vc/3EAxV40CJ1Sue1NjDcWTCWpM= Xref: csiph.com comp.lang.c:161927 David Brown writes: > On 16/07/2021 00:07, Öö Tiib wrote: >> On Friday, 16 July 2021 at 00:12:40 UTC+3, Ben Bacarisse wrote: >>> Öö Tiib writes: >>> >>>> On Thursday, 15 July 2021 at 23:21:37 UTC+3, Andrey Tarasevich wrote: >>>>> 6.3.2/1 says that >>>>> >>>>> 1 [...] A modifiable lvalue is an lvalue that does not have array >>>>> type, [...] >>>>> >>>>> Based on that, arrays are non-modifiable lvalues. We all know what it >>>>> actually means. But is there any context in the standard in which this >>>>> non-modifiability of array lvalues would actually _matter_, would >>>>> actually interact with some other standard requirement? >>>>> >>>>> One thing that comes to mind is a constraint on assignment operators >>>>> (6.5.16/2) >>>>> >>>>> 2 An assignment operator shall have a modifiable lvalue as its left >>>>> operand. >>>>> >>>>> So, one can combine 6.3.2/1 and 6.5.16/2 and conclude that one can't >>>>> assign to arrays. But I believe that constraints are intended/supposed >>>>> to be applied after automatic implicit conversions. And since LHS of >>>>> assignment is not one of the contexts excluded from array type decay, >>>>> said decay is already sufficient to prevent assignment to arrays. >>>>> >>>>> Am I right here? Is the constraint of 6.5.16/2 supposed to be applied >>>>> before automatic implicit conversions or after them? >>>>> >>>>> And if the answer is "after", then is there any other context in C >>>>> standard where non-modifiability of array lvalues would make a difference? >>>> >>>> It is so that we can't modify address of array so >>>> rest of operators that can modify lvalue like ++ or += also >>>> will be rejected on case of an array. But I might misunderstand >>>> what you are asking. >>> >>> Yes, you've missed the point of the question. Lvalue expressions of >>> array type are, in almost all situations, converted to pointers to the >>> first element of the array, and *the result is no longer an lvalue*. >>> (The exceptions are the operands of &, sizeof and _Alignof and when a >>> string literal is used to initialise an array.) >>> >>> Thus, given `int a[1]`, the expression `a++` is invalid because the >>> operand is not an lvalue at all. >> >> Yes and so a = b is invalid because a turns into something that is >> not lvalue at all. But saying that it is not modifiable does not hurt? > > As far as I can tell (there are others here that are better than I at > interpreting the exact wording of the standards), the wording in the > standard has been misinterpreted here. > > The standard says "A modifiable lvalue is an lvalue that does not have > array type". When applied to "a = b", this has been interpreted to mean > that "a" is an lvalue of array type and therefore a non-modifiable > lvalue, so you cannot use the assignment. This is, AFAICS, subtly > incorrect - used here, "a" is converted to a non-lvalue pointer to its > first element. It is not an lvalue at all, modifiable or non-modifiable. I think that both of the previous posters in this thread, Ben and Öö, have correctly said essentially the same think you're saying, that `a` (after the array-to-pointer conversion) is not an lvalue at all. I'm not sure that anyone here has misinterpreted it in the way you suggest. If you write int arr[10]; size_t s = sizeof arr; then the expression arr in the second line is an lvalue (because it designates an object and there's no array-to-pointer conversion) *and* is not a modifiable lvalue (because it's of array type). If the "does not have array type" wording were dropped, then arr would be a modifiable lvalue -- but there's no attempt to modify it, so it doesn't matter. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for Philips void Void(void) { Void(); } /* The recursive call of the void */