Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #161918 > unrolled thread
| Started by | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| First post | 2021-07-15 13:21 -0700 |
| Last post | 2021-07-23 23:26 -0700 |
| Articles | 20 on this page of 28 — 9 participants |
Back to article view | Back to comp.lang.c
Array is an non-modifiable lvalue - where does it matter? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-07-15 13:21 -0700
Re: Array is an non-modifiable lvalue - where does it matter? Öö Tiib <ootiib@hot.ee> - 2021-07-15 13:55 -0700
Re: Array is an non-modifiable lvalue - where does it matter? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-07-15 22:12 +0100
Re: Array is an non-modifiable lvalue - where does it matter? Öö Tiib <ootiib@hot.ee> - 2021-07-15 15:07 -0700
Re: Array is an non-modifiable lvalue - where does it matter? David Brown <david.brown@hesbynett.no> - 2021-07-16 09:52 +0200
Re: Array is an non-modifiable lvalue - where does it matter? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-07-16 02:31 -0700
Re: Array is an non-modifiable lvalue - where does it matter? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-07-16 10:59 -0700
Re: Array is an non-modifiable lvalue - where does it matter? David Brown <david.brown@hesbynett.no> - 2021-07-17 16:23 +0200
Re: Array is an non-modifiable lvalue - where does it matter? James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-07-17 20:14 -0400
Re: Array is an non-modifiable lvalue - where does it matter? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-07-15 14:36 -0700
Re: Array is an non-modifiable lvalue - where does it matter? Öö Tiib <ootiib@hot.ee> - 2021-07-15 15:19 -0700
Re: Array is an non-modifiable lvalue - where does it matter? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-07-15 14:06 -0700
Re: Array is an non-modifiable lvalue - where does it matter? James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-07-16 14:22 -0400
Re: Array is an non-modifiable lvalue - where does it matter? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-07-16 11:43 -0700
Re: Array is an non-modifiable lvalue - where does it matter? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-07-17 18:24 -0700
Re: Array is an non-modifiable lvalue - where does it matter? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-07-17 20:29 -0700
Re: Array is an non-modifiable lvalue - where does it matter? Siri Cruise <chine.bleu@yahoo.com> - 2021-07-17 21:25 -0700
Re: Array is an non-modifiable lvalue - where does it matter? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-07-16 15:22 -0700
Re: Array is an non-modifiable lvalue - where does it matter? Kaz Kylheku <563-365-8930@kylheku.com> - 2021-07-16 22:21 +0000
Re: Array is an non-modifiable lvalue - where does it matter? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-07-16 23:27 -0700
Re: Array is an non-modifiable lvalue - where does it matter? Kaz Kylheku <563-365-8930@kylheku.com> - 2021-07-17 16:53 +0000
Re: Array is an non-modifiable lvalue - where does it matter? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-07-17 10:49 -0700
Re: Array is an non-modifiable lvalue - where does it matter? Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-07-17 14:01 -0700
Re: Array is an non-modifiable lvalue - where does it matter? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2021-07-18 02:09 +0100
Re: Array is an non-modifiable lvalue - where does it matter? James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-07-17 20:12 -0400
Re: Array is an non-modifiable lvalue - where does it matter? "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-07-17 13:20 -0700
Re: Array is an non-modifiable lvalue - where does it matter? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2021-07-19 14:44 -0700
Re: Array is an non-modifiable lvalue - where does it matter? "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-07-23 23:26 -0700
Page 1 of 2 [1] 2 Next page →
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2021-07-15 13:21 -0700 |
| Subject | Array is an non-modifiable lvalue - where does it matter? |
| Message-ID | <scq5c5$tql$1@dont-email.me> |
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? -- Best regards, Andrey Tarasevich
[toc] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2021-07-15 13:55 -0700 |
| Message-ID | <5c1d96ea-c554-4aa1-b0db-a7729027ee04n@googlegroups.com> |
| In reply to | #161918 |
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.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2021-07-15 22:12 +0100 |
| Message-ID | <875yxbth6r.fsf@bsb.me.uk> |
| In reply to | #161919 |
Öö Tiib <ootiib@hot.ee> 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. Andrey is asking whether there are any situations where it matters that the standard excludes array-valued lvalues from being modifiable lvalues. Could that wording simply have been left out or would that permit something, not excluded by other wording, from being valid C? I *think* the answer is yes -- there would be no harm (other than maybe a loss of clarity) in removing that wording. But I had deliberately not answered because this is the sort of question that requires a more thorough knowledge of the standard than I possess to answer with any confidence. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2021-07-15 15:07 -0700 |
| Message-ID | <e6132d4c-d915-492a-a76e-2d4a2062d353n@googlegroups.com> |
| In reply to | #161921 |
On Friday, 16 July 2021 at 00:12:40 UTC+3, Ben Bacarisse wrote: > Öö Tiib <oot...@hot.ee> 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? > Andrey is asking whether there are any situations where it matters that > the standard excludes array-valued lvalues from being modifiable > lvalues. Could that wording simply have been left out or would that > permit something, not excluded by other wording, from being valid C? > > I *think* the answer is yes -- there would be no harm (other than maybe > a loss of clarity) in removing that wording. But I had deliberately not > answered because this is the sort of question that requires a more > thorough knowledge of the standard than I possess to answer with any > confidence. Thanks for clarifying. I don't think that it is bad when standard repeats something over even if it is deducible from other parts. Especially about arrays that seem to be constant source of confusion among people who try to learn C.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-07-16 09:52 +0200 |
| Message-ID | <scrdrf$g4r$1@dont-email.me> |
| In reply to | #161923 |
On 16/07/2021 00:07, Öö Tiib wrote: > On Friday, 16 July 2021 at 00:12:40 UTC+3, Ben Bacarisse wrote: >> Öö Tiib <oot...@hot.ee> 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.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-07-16 02:31 -0700 |
| Message-ID | <87eeby38rd.fsf@nosuchdomain.example.com> |
| In reply to | #161925 |
David Brown <david.brown@hesbynett.no> writes:
> On 16/07/2021 00:07, Öö Tiib wrote:
>> On Friday, 16 July 2021 at 00:12:40 UTC+3, Ben Bacarisse wrote:
>>> Öö Tiib <oot...@hot.ee> 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 */
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2021-07-16 10:59 -0700 |
| Message-ID | <scshd7$r7p$1@dont-email.me> |
| In reply to | #161925 |
On 7/16/2021 12:52 AM, David Brown wrote: > > 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. > That's actually part of the question I was asking originally. You are implicitly insisting that the array-to-pointer conversion should be applied first, and only after that the constraints of the assignment operator should be checked. Can you provide a reference to C standard that would indicate that it is supposed to be done in that specific order, and not the other way around? For example, C++ standard is known to use wording like "this (conversion | transformation | adjustment) is applied before and further (analysis | consideration) is performed" in order to eliminate such ambiguities. But I don't see anything like that in C standard. One can argue that it doesn't matter since the outcome is functionally the same either way. But still... the question is intended as a "language-lawyer" one. -- Best regards, Andrey Tarasevich
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2021-07-17 16:23 +0200 |
| Message-ID | <scup4s$498$1@dont-email.me> |
| In reply to | #161937 |
On 16/07/2021 19:59, Andrey Tarasevich wrote: > On 7/16/2021 12:52 AM, David Brown wrote: >> >> 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. >> > > That's actually part of the question I was asking originally. > > You are implicitly insisting that the array-to-pointer conversion should > be applied first, and only after that the constraints of the assignment > operator should be checked. > I'm not sure I'd use the word "insisting", but that is correct. > Can you provide a reference to C standard that would indicate that it is > supposed to be done in that specific order, and not the other way around? Assignment is an operator, and thus the left-hand side is an expression. 6.3.2.1p3 says: """ Except when it is the operand of the sizeof operator, or the unary & operator, or is a string literal used to initalize 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. """ As for the order in which the conversions are done here, I think these come from the grammar of the language - subexpressions must be converted before the operand using them. I can't conceive of how a language could do anything else here, but it is given in 6.5p1 anyway. (Generated code can do calculations in any order as long as the results are correct.) > > For example, C++ standard is known to use wording like "this (conversion > | transformation | adjustment) is applied before and further (analysis | > consideration) is performed" in order to eliminate such ambiguities. > Yes, but that is because in C++ you can have many implicit conversions and thus the ordering is not clear. > But I don't see anything like that in C standard. One can argue that it > doesn't matter since the outcome is functionally the same either way. > But still... the question is intended as a "language-lawyer" one. >
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2021-07-17 20:14 -0400 |
| Message-ID | <scvrp8$auf$2@dont-email.me> |
| In reply to | #161946 |
On 7/17/21 10:23 AM, David Brown wrote: > On 16/07/2021 19:59, Andrey Tarasevich wrote: ... >> You are implicitly insisting that the array-to-pointer conversion should >> be applied first, and only after that the constraints of the assignment >> operator should be checked. >> > > I'm not sure I'd use the word "insisting", but that is correct. > >> Can you provide a reference to C standard that would indicate that it is >> supposed to be done in that specific order, and not the other way around? > > Assignment is an operator, and thus the left-hand side is an expression. > 6.3.2.1p3 says: > > """ > Except when it is the operand of the sizeof operator, or the unary & > operator, or is a string literal used to initalize 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. > """ > > As for the order in which the conversions are done here, I think these > come from the grammar of the language - subexpressions must be converted > before the operand using them. I can't conceive of how a language could > do anything else here, but it is given in 6.5p1 anyway. (Generated code > can do calculations in any order as long as the results are correct.) It's not about the order in which any of the operations occur that matters. It's about whether the constraints apply before or after the conversions. Constraints are not actions, and the standard is therefore less specific about how they are sequenced relative to actual activities.
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2021-07-15 14:36 -0700 |
| Message-ID | <scq9pd$j11$1@dont-email.me> |
| In reply to | #161919 |
On 7/15/2021 1:55 PM, Öö Tiib wrote: > > 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. Um... I don't see what you are trying to say here. There's no such concept in C as "modifying an address of an exiting object". No need to block or prevent it, for arrays or for anything else. -- Best regards, Andrey Tarasevich
[toc] | [prev] | [next] | [standalone]
| From | Öö Tiib <ootiib@hot.ee> |
|---|---|
| Date | 2021-07-15 15:19 -0700 |
| Message-ID | <bd014848-757b-4a01-80d4-a3be029ff20fn@googlegroups.com> |
| In reply to | #161922 |
On Friday, 16 July 2021 at 00:36:57 UTC+3, Andrey Tarasevich wrote: > On 7/15/2021 1:55 PM, Öö Tiib wrote: > > > > 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. > Um... I don't see what you are trying to say here. There's no such > concept in C as "modifying an address of an exiting object". No need to > block or prevent it, for arrays or for anything else. Yes, but that does not matter that there are no features or concepts in C. After figuring that array decays to pointer a novice tries to modify that pointer sooner or later. Sometimes "successfully" as array "parameter" is actually a pointer. Being maximally brief about that unlucky and confusing feature is bad idea.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-07-15 14:06 -0700 |
| Message-ID | <87im1b2snz.fsf@nosuchdomain.example.com> |
| In reply to | #161918 |
Andrey Tarasevich <andreytarasevich@hotmail.com> writes:
> 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?
My first thought is that the statement is redundant (and that's not
necessarily a bad thing). Other requirements imply that you can't
assign to arrays, but it doesn't hurt to have an explicit statement to
that effect.
The full definition is:
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.
I *think* that dropping the "does not have array type" wouldn't change
anything, but it's probably clearer as it is.
--
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 */
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2021-07-16 14:22 -0400 |
| Message-ID | <scsiq3$ens$1@dont-email.me> |
| In reply to | #161918 |
On 7/15/21 4:21 PM, 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. The Rationale says "the fact that a[i] is a modifiable lvalue while a is not has puzzled many students of the language. A more precise description was incorporated in C89 in the hope of combatting this confusion." I have a vague memory that this wording is connected to a subtle issue with functions that return values of struct type, where the struct contains an array member. But I can't remember what the issue was.
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2021-07-16 11:43 -0700 |
| Message-ID | <scsk02$v8i$1@dont-email.me> |
| In reply to | #161938 |
On 7/16/2021 11:22 AM, James Kuyper wrote:
>
> I have a vague memory that this wording is connected to a subtle issue
> with functions that return values of struct type, where the struct
> contains an array member. But I can't remember what the issue was.
>
The issue(s) stem from the combination of the following bits and pieces:
1. Function return is always an rvalue
2. Member array of an rvalue struct object is also an rvalue
3. The result of unary '*' is always an lvalue. And, say, `[]` is
defined through unary '*' and '+'.
2 and 3 conflict with each other.
C89/90 resolved this problem by stating that array-to-pointer conversion
is only applicable to lvalue arrays. This basically made rvalue arrays
inaccessible
struct S { int a[10]; };
struct S foo(void)
{
struct S s = { 0 };
return s;
}
int main()
{
int i = foo().a[0]; /* <- error in C89/90 */
return 0;
}
The above code would report a constraint violation: it is not possible
to apply `[]` to `foo().a`.
C99 decided to change that. Starting from C99 array-to-pointer
conversion is applicable to rvalue arrays as well, which legalized
int i = foo().a[0]; /* <- OK in C99 */
but created another issue
foo().a[0] = 42; /* are we assigning to an rvalue here? */
C99 cops out of this latter problem by stating that the behavior is
undefined in this case.
--
Best regards,
Andrey Tarasevich
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2021-07-17 18:24 -0700 |
| Message-ID | <scvvrv$s1r$1@dont-email.me> |
| In reply to | #161939 |
On 7/16/2021 11:43 AM, Andrey Tarasevich wrote:
> On 7/16/2021 11:22 AM, James Kuyper wrote:
>>
>> I have a vague memory that this wording is connected to a subtle issue
>> with functions that return values of struct type, where the struct
>> contains an array member. But I can't remember what the issue was.
>>
>
> The issue(s) stem from the combination of the following bits and pieces:
>
> 1. Function return is always an rvalue
> 2. Member array of an rvalue struct object is also an rvalue
> 3. The result of unary '*' is always an lvalue. And, say, `[]` is
> defined through unary '*' and '+'.
>
> 2 and 3 conflict with each other.
> ...
> C99 cops out of this latter problem by stating that the behavior is
> undefined in this case.
I see that I fell victim to the same confusion I'm carefully trying to
avoid.
Of course, there's no real conflict between 2 and 3. Value category is a
property of an expression, not a property of an object. There's nothing
wrong with having two different expressions that expose the same
underlying object as an lvalue and as an rvalue at the same time.
C89/90 apparently did not want to introduce the concept of "temporary
lifetime". That's why it simply prohibited access to arrays inside
rvalue structs.
C99 decided that this is unnecessarily restrictive, and now we have
lvalue access to elements of arrays inside rvalue structs. But still C99
is afraid to allow us to modify these elements. Granted, the use cases
will always be pronouncedly contrived
#include <stdio.h>
struct S { int a[10]; };
struct S foo()
{
return (struct S) { 0 };
}
int main()
{
int *p;
p = foo().a, p[5] = 42, printf("%d\n", p[5]); // undefined behavior
}
but in some corner cases it could have been useful...
--
Best regards,
Andrey Tarasevich
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-07-17 20:29 -0700 |
| Message-ID | <87wnpo1eq9.fsf@nosuchdomain.example.com> |
| In reply to | #161957 |
Andrey Tarasevich <andreytarasevich@hotmail.com> writes:
> On 7/16/2021 11:43 AM, Andrey Tarasevich wrote:
>> On 7/16/2021 11:22 AM, James Kuyper wrote:
>>>
>>> I have a vague memory that this wording is connected to a subtle issue
>>> with functions that return values of struct type, where the struct
>>> contains an array member. But I can't remember what the issue was.
>>>
>> The issue(s) stem from the combination of the following bits and
>> pieces:
>> 1. Function return is always an rvalue
>> 2. Member array of an rvalue struct object is also an rvalue
>> 3. The result of unary '*' is always an lvalue. And, say, `[]` is
>> defined through unary '*' and '+'.
>> 2 and 3 conflict with each other.
>> ...
>
>> C99 cops out of this latter problem by stating that the behavior is
>> undefined in this case.
>
> I see that I fell victim to the same confusion I'm carefully trying to
> avoid.
>
> Of course, there's no real conflict between 2 and 3. Value category is
> a property of an expression, not a property of an object. There's
> nothing wrong with having two different expressions that expose the
> same underlying object as an lvalue and as an rvalue at the same time.
>
> C89/90 apparently did not want to introduce the concept of "temporary
> lifetime". That's why it simply prohibited access to arrays inside
> rvalue structs.
Unless I'm missing something, C89/C90 didn't *prohibit* access to arrays
inside rvalue structs. The idea was simply overlooked (and it is rather
obscure). It says that an array expression is converted to a pointer
expression that points to the initial element of "the array object",
overlooking the rare cases when there is no array object to point to.
It was a bug in the standard, fixed in C11.
> C99 decided that this is unnecessarily restrictive, and now we have
> lvalue access to elements of arrays inside rvalue structs. But still
> C99 is afraid to allow us to modify these elements. Granted, the use
> cases will always be pronouncedly contrived
>
> #include <stdio.h>
>
> struct S { int a[10]; };
>
> struct S foo()
> {
> return (struct S) { 0 };
> }
>
> int main()
> {
> int *p;
> p = foo().a, p[5] = 42, printf("%d\n", p[5]); // undefined behavior
> }
>
> but in some corner cases it could have been useful...
That was resolved in C11, not C99. C11 introduced the concept of
"temporary lifetime" for non-lvalue expressions of structure or union
type with an array member. See N1570 6.2.4p8.
I can't think of any cases where allowing modification of an object with
temporary lifetime would be useful. In your admittedly contrived
example, if you wanted the struct S object to be persistent, you could
arrange for that easily enough.
(Another approach might have been to add a rule saying that foo().a
yields a pointer of type `const int*`, but that's a bit ugly.)
--
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 */
[toc] | [prev] | [next] | [standalone]
| From | Siri Cruise <chine.bleu@yahoo.com> |
|---|---|
| Date | 2021-07-17 21:25 -0700 |
| Message-ID | <chine.bleu-2C5905.21251617072021@reader.eternal-september.org> |
| In reply to | #161957 |
It's easy enough if you extend the type system to include
lvalueness.
T Type T.
&T A T lvalue. & can only appear as the outermost.
*T A T pointer.
(implied) &T --> T Load operator.
= &T=T --> T Assign operator.
& &T --> *T Address operator.
* *T --> &T Dereference operator.
(...) *T(...) --> T Derefence and call operator.
[...] *T[e] --> &T Array index.
P u; Simple declaration of identifier u with type &P.
Q *v; Declare v with type &*Q.
R w[]; Declare w with type *R.
(&P)u = (T)e; Coerce e to (P) and assign.
(&T)e = (&P)u; Load u; coerce to T, assign to e.
(&P)u[...] [...] not defined for &P or P.
&(&P)u --> (*P) Address operator.
*(&P)u * not defined for &P or P.
(&*Q)v = (T)e; Coerce e to (*Q) and assign.
(&T)e = (&*Q)v; Load v; coerce to T, assign to e.
(&*Q)v[...] --> &Q Load v to (*Q); apply array index.
&(&*Q)v --> (**Q) Address operator.
*(&*Q)v --> (&Q) Load v to (*Q) and deref.
(*R)w = (T)e; = not defined for *R.
(&T)e = (*Q)w; Coerce to T, assign to e.
(*R)w[...] --> &R Apply array index.
&(*R)w & not defined for *R. By special
dispensation the & is ignored and
returns (*R)w.
*(*R)w --> (&R) Apply deref.
--
:-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted. @
'I desire mercy, not sacrifice.' /|\
Discordia: not just a religion but also a parody. This post / \
I am an Andrea Doria sockpuppet. insults Islam. Mohammed
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-07-16 15:22 -0700 |
| Message-ID | <875yx93nnb.fsf@nosuchdomain.example.com> |
| In reply to | #161938 |
James Kuyper <jameskuyper@alumni.caltech.edu> writes:
> On 7/15/21 4:21 PM, 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.
>
> The Rationale says "the fact that a[i] is a modifiable lvalue while a is
> not has puzzled many students of the language. A more precise
> description was incorporated in C89 in the hope of combatting this
> confusion."
>
> I have a vague memory that this wording is connected to a subtle issue
> with functions that return values of struct type, where the struct
> contains an array member. But I can't remember what the issue was.
I think that case is separate from what we're discussing here, though of
course they're both related to the odd way C treats array expressions.
This thread is about lvalues that are of array type.
The struct return issue is about expressions of array type that are not
lvalues (something that's no longer possible as of C11, I think).
In C90 and C99, if a function returns a struct with a member of array
type and you refer to the name of that member:
func().array_member
then that's an expression of array type which is converted (in most
contexts) to a pointer to the initial element of "the array object".
The problem: In that specific case there is no array object (a function
call yields a value, not an object). C11 resolved that by inventing an
object with "temporary lifetime". There are cases other than function
calls where this shows up; the assignment, comma, and conditional
operators can yield non-lvalues of struct type.
--
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 */
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <563-365-8930@kylheku.com> |
|---|---|
| Date | 2021-07-16 22:21 +0000 |
| Message-ID | <20210716145835.570@kylheku.com> |
| In reply to | #161918 |
On 2021-07-15, Andrey Tarasevich <andreytarasevich@hotmail.com> 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?
If what you are getting at is this: could a C dialect provide complete
support for array passing, returning and assignment, while conforming
to the current standard?
The answer is no.
A conforming extension of behavior could be to allow arrays to be
modifiable lvalues: emit the required diagnostic, and then allow
assignment or initialization; e.g.
int a[10] = { 0 };
int b[10] = a;
int c[10];
c = b;
FUrthermore, function declaration syntax for returning arrays could
be added without conflict:
int foo(void)[10];
c = foo();
Where we run aground is the fact that parameter declarations of
array type actually declare a pointer. This is the case even
if they specify a dimension:
void foo(int a[42]); // actually (int *a)
that kind of puts a monkey wrench into an otherwise reasonably
tidy plan to extend the language.
Passing arguments to parameters is very similar to assignment;
An assignable array proposal which doesn't permit passing would
introduce an ugly inconsistency.
> 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.
Indeed, an implementation can implement the constraint that arrays are not
modifiable lvalues simply by imposing the "decay rule" in all contexts
other than when the array is the operand of & (address-of) or sizeof.
The array is then not assignable by virtue of having been converted
to a pointer which is not an lvalue. If it's not an lvalue, it's not
a modifiable lvalue: requirement satisfied.
> Am I right here? Is the constraint of 6.5.16/2 supposed to be applied
> before automatic implicit conversions or after them?
It looks moot. Before conversion to pointer, you have an array lvalue,
and the requirement says that it' not modifiable. Thus, cannot assign to
it. After conversion to pointer, you don't have an lvalue. Not
assignable, either.
Which case it is basically is only germane to the wording of the
constraint violation diagnostic, and that is not specified.
A compiler which diagnoses the assignment as "cannot assign to a
calculated pointer" is conforming; it has produced the required
diagnostic.
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2021-07-16 23:27 -0700 |
| Message-ID | <sctt7r$88g$1@dont-email.me> |
| In reply to | #161942 |
On 7/16/2021 3:21 PM, Kaz Kylheku wrote: > If what you are getting at is this: could a C dialect provide complete > support for array passing, returning and assignment, while conforming > to the current standard? > > The answer is no. No, no, no, I'm not interested in that at all. >> Am I right here? Is the constraint of 6.5.16/2 supposed to be applied >> before automatic implicit conversions or after them? > > It looks moot. Before conversion to pointer, you have an array lvalue, > and the requirement says that it' not modifiable. Thus, cannot assign to > it. After conversion to pointer, you don't have an lvalue. Not > assignable, either. > Yes, it is moot for the specific case of arrays. But at the same time it intuitively looks and feels like a more general issue. Again, what comes first: automatic implicit conversions or constraint checks? And even if this currently proves to be moot in all other contexts as well, it still appears to be something kinda... too important to be left unspecified. -- Best regards, Andrey Tarasevich
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.c
csiph-web