digitalmars.D.learn - Multiple assignment
- bearophile (30/30) Feb 25 2011 Is this program showing a bug in multiple assignments (DMD 2.052)?
- simendsjo (11/41) Feb 25 2011 I couldn't find any info on the comma expression in the language
- bearophile (15/25) Feb 25 2011 Right. But my code was wrong, I meant to write this:
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (5/8) Feb 25 2011 I think that's undefined behavior in C and C++. It is not defined
- Jonathan M Davis (11/20) Feb 25 2011 No, that should be perfectly defined. What's undefined is when you do so...
- Steven Schveighoffer (5/24) Feb 25 2011 Let me fix that for you:
- Jonathan M Davis (3/30) Feb 25 2011 LOL. Yes. I forgot to alter j in the expression. Good catch.
- spir (9/11) Feb 26 2011 That should be illegal: a statement used as expression, but keeping it's...
- Jonathan M Davis (10/18) Feb 26 2011 Umm. There is no statement used as an expression here. The only statemen...
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (43/59) Feb 25 2011 Standard texts are very difficult to read. I found a 2005 draft of the
- Jonathan M Davis (10/83) Feb 25 2011 Bleh. Well, good to know. Walter wants to make the order such evaluation...
- Dan Olson (21/38) Feb 26 2011 Java made assignment well defined by saying:
- Jonathan M Davis (15/64) Feb 26 2011 The assignment order is well-defined in both C++ an D, but the order of=...
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (10/40) Feb 25 2011 I haven't heard about multiple assignments but that's the comma operator...
- spir (9/21) Feb 26 2011 I'm far to be a C expert, but that looks like very normal C semantics, a...
Is this program showing a bug in multiple assignments (DMD 2.052)? void main() { int i; int[2] x; i, x[i] = 1; assert(x == [1, 0]); // OK int j; int[2] y; y[j], j = 1; assert(y == [0, 0]); // Not OK } At the end of the program I expect y to be [1,0] instead of [0,0]. Yet this C program with GCC: #include "stdio.h" int main() { int i = 0; int x[2] = {0, 0}; i, x[i] = 1; printf("%d %d\n", x[0], x[1]); int j = 0; int y[2] = {0, 0}; y[j], j = 1; printf("%d %d\n", y[0], y[1]); return 0; } has the same output as DMD: 1 0 0 0 Bye, bearophile
Feb 25 2011
On 26.02.2011 01:56, bearophile wrote:Is this program showing a bug in multiple assignments (DMD 2.052)? void main() { int i; int[2] x; i, x[i] = 1; assert(x == [1, 0]); // OK int j; int[2] y; y[j], j = 1; assert(y == [0, 0]); // Not OK } At the end of the program I expect y to be [1,0] instead of [0,0]. Yet this C program with GCC: #include "stdio.h" int main() { int i = 0; int x[2] = {0, 0}; i, x[i] = 1; printf("%d %d\n", x[0], x[1]); int j = 0; int y[2] = {0, 0}; y[j], j = 1; printf("%d %d\n", y[0], y[1]); return 0; } has the same output as DMD: 1 0 0 0 Bye, bearophileI couldn't find any info on the comma expression in the language reference, but this was my first google hit: """ A comma expression contains two operands of any type separated by a comma and has *left-to-right* associativity. The left operand is fully evaluated, possibly producing side effects, and its value, if there is one, is *discarded*. The right operand is then evaluated. The type and value of the result of a comma expression are those of its right operand, after the usual unary conversions """
Feb 25 2011
simendsjo:I couldn't find any info on the comma expression in the language reference, but this was my first google hit: """ A comma expression contains two operands of any type separated by a comma and has *left-to-right* associativity. The left operand is fully evaluated, possibly producing side effects, and its value, if there is one, is *discarded*. The right operand is then evaluated. The type and value of the result of a comma expression are those of its right operand, after the usual unary conversions """Right. But my code was wrong, I meant to write this: void main() { int i; int[2] x; i = x[i] = 1; assert(x == [1, 0]); // OK int j; int[2] y; y[j] = j = 1; assert(y == [0, 1]); // Not OK } And I think it is working as you expect it to. Thank you and sorry for the noise, bearophile
Feb 25 2011
On 02/25/2011 05:09 PM, bearophile wrote:int j; int[2] y; y[j] = j = 1;I think that's undefined behavior in C and C++. It is not defined whether j's previous or past value is used in y[j]. I would expect the situation be the same in D. Ali
Feb 25 2011
On Friday, February 25, 2011 17:31:36 Ali =C3=87ehreli wrote:On 02/25/2011 05:09 PM, bearophile wrote: > int j; > int[2] y; > y[j] =3D j =3D 1; =20 I think that's undefined behavior in C and C++. It is not defined whether j's previous or past value is used in y[j]. =20 I would expect the situation be the same in D.No, that should be perfectly defined. What's undefined is when you do somet= hing=20 like func(j, y[j]). The evaluation order of the function arguments is undef= ined.=20 However, the evaluation order when dealing with an assignment should be de= fined.=20 I _could_ be wrong about that, but there's no question that the assignments= =20 themselves are guaranteed to be done in right-to-left order. =2D Jonathan M Davis
Feb 25 2011
On Fri, 25 Feb 2011 21:10:59 -0500, Jonathan M Davis <jmdavisProg gmx.com> wrote:On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote:Let me fix that for you: func(j++, y[j]) -SteveOn 02/25/2011 05:09 PM, bearophile wrote: > int j; > int[2] y; > y[j] = j = 1; I think that's undefined behavior in C and C++. It is not defined whether j's previous or past value is used in y[j]. I would expect the situation be the same in D.No, that should be perfectly defined. What's undefined is when you do something like func(j, y[j]). The evaluation order of the function arguments is undefined. However, the evaluation order when dealing with an assignment should be defined. I _could_ be wrong about that, but there's no question that the assignments themselves are guaranteed to be done in right-to-left order.
Feb 25 2011
On Friday, February 25, 2011 19:26:14 Steven Schveighoffer wrote:On Fri, 25 Feb 2011 21:10:59 -0500, Jonathan M Davis <jmdavisProg gmx.com> =20 wrote:LOL. Yes. I forgot to alter j in the expression. Good catch. =2D Jonathan M DavisOn Friday, February 25, 2011 17:31:36 Ali =C3=87ehreli wrote:=20 Let me fix that for you: =20 func(j++, y[j])On 02/25/2011 05:09 PM, bearophile wrote: > int j; > int[2] y; > y[j] =3D j =3D 1; =20 I think that's undefined behavior in C and C++. It is not defined whether j's previous or past value is used in y[j]. =20 I would expect the situation be the same in D.=20 No, that should be perfectly defined. What's undefined is when you do something like func(j, y[j]). The evaluation order of the function arguments is undefined. However, the evaluation order when dealing with an assignment should be defined. I _could_ be wrong about that, but there's no question that the assignments themselves are guaranteed to be done in right-to-left order.
Feb 25 2011
On 02/26/2011 04:26 AM, Steven Schveighoffer wrote:Let me fix that for you: func(j++, y[j])That should be illegal: a statement used as expression, but keeping it's effect anyway, and not the least kind of, namely an assignment, meaning a change of the program state. Denis -- _________________ vita es estrany spir.wikidot.com
Feb 26 2011
On Saturday 26 February 2011 00:51:45 spir wrote:On 02/26/2011 04:26 AM, Steven Schveighoffer wrote:Umm. There is no statement used as an expression here. The only statement is a function call. Both j++ and y[j] are expressions. Even the function call is an expression. It's just that if it's followed by a semi-colon, it becomes a statement. Regardless, the best solution is to make the order of evaluation of the function arguments fixed at left-to-right instead of undefined. And as I understand it, Walter intends to make D do that at some point. It's just that he hasn't gotten around to it yet. - Jonathan M DavisLet me fix that for you: func(j++, y[j])That should be illegal: a statement used as expression, but keeping it's effect anyway, and not the least kind of, namely an assignment, meaning a change of the program state.
Feb 26 2011
On 02/25/2011 06:10 PM, Jonathan M Davis wrote:On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote:Standard texts are very difficult to read. I found a 2005 draft of the C++ standard. 5 Expressions, paragraph 4: <quote> Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expres- sions, and the order in which side effects take place, is unspecified.58) Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined. [ Example: i = v [ i ++]; / / the behavior is undefined i = 7 , i ++ , i ++; / / i becomes 9 i = ++ i + 1; / / the behavior is undefined i = i + 1; / / the value of i is incremented — end example ] </quote> To complete, footnote 58 is: <quote> 58) The precedence of operators is not directly specified, but it can be derived from the syntax. </quote> The section for the assignment operator does not mention anything to the contrary. According to my current understanding and my now-hazy recollections of old discussions on C++ news groups, in the following statement a() = b() = c(); the value of c() is assigned to b(), and the value of that expression is assigned to a(); but the order in which the three expressions are evaluated are unspecified. Hence, if the code behaves contrary to 5.1 above, it has undefined behavior. This was bearophile's statement: y[j] = j = 1; The assignment operators do not introduce sequence points; there are only two: before and after the whole line above. The code does not obey "the prior value shall be accessed only to determine the value to be stored". Above, the prior value is used to determine which element of y is being assigned to. AliOn 02/25/2011 05:09 PM, bearophile wrote: > int j; > int[2] y; > y[j] = j = 1; I think that's undefined behavior in C and C++. It is not defined whether j's previous or past value is used in y[j]. I would expect the situation be the same in D.No, that should be perfectly defined. What's undefined is when you do something like func(j, y[j]). The evaluation order of the function arguments is undefined. However, the evaluation order when dealing with an assignment should be defined. I _could_ be wrong about that, but there's no question that the assignments themselves are guaranteed to be done in right-to-left order. - Jonathan M Davis
Feb 25 2011
On Friday 25 February 2011 22:32:47 Ali =C3=87ehreli wrote:On 02/25/2011 06:10 PM, Jonathan M Davis wrote:Bleh. Well, good to know. Walter wants to make the order such evaluations=20 ordered in D at some point though, so eventually it won't be a problem in D= -=20 though it'll obviously still be a problem in C++. Regardless, avoiding to a= lter=20 a variable and use it multiple times within the same statement or expressio= n is=20 a good idea. =2D Jonathan M davisOn Friday, February 25, 2011 17:31:36 Ali =C3=87ehreli wrote:=20 Standard texts are very difficult to read. I found a 2005 draft of the C++ standard. 5 Expressions, paragraph 4: =20 <quote> Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expres- sions, and the order in which side effects take place, is unspecified.58) Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined. [ Example: i =3D v [ i ++]; / / the behavior is undefined i =3D 7 , i ++ , i ++; / / i becomes 9 i =3D ++ i + 1; / / the behavior is undefined i =3D i + 1; / / the value of i is incremented =E2=80=94 end example ] </quote> =20 To complete, footnote 58 is: =20 <quote> 58) The precedence of operators is not directly specified, but it can be derived from the syntax. </quote> =20 The section for the assignment operator does not mention anything to the contrary. According to my current understanding and my now-hazy recollections of old discussions on C++ news groups, in the following statement =20 a() =3D b() =3D c(); =20 the value of c() is assigned to b(), and the value of that expression is assigned to a(); but the order in which the three expressions are evaluated are unspecified. =20 Hence, if the code behaves contrary to 5.1 above, it has undefined behavior. =20 This was bearophile's statement: =20 y[j] =3D j =3D 1; =20 The assignment operators do not introduce sequence points; there are only two: before and after the whole line above. The code does not obey "the prior value shall be accessed only to determine the value to be stored". Above, the prior value is used to determine which element of y is being assigned to.On 02/25/2011 05:09 PM, bearophile wrote: > int j; > int[2] y; > y[j] =3D j =3D 1; =20 I think that's undefined behavior in C and C++. It is not defined whether j's previous or past value is used in y[j]. =20 I would expect the situation be the same in D.=20 No, that should be perfectly defined. What's undefined is when you do something like func(j, y[j]). The evaluation order of the function arguments is undefined. However, the evaluation order when dealing with an assignment should be defined. I _could_ be wrong about that, but there's no question that the assignments themselves are guaranteed to be done in right-to-left order. =20 - Jonathan M Davis
Feb 25 2011
Jonathan M Davis <jmdavisProg gmx.com> writes:On Friday, February 25, 2011 17:31:36 Ali Çehreli wrote:Java made assignment well defined by saying: First evaluate the left-hand-side to determine a variable to assign to. Then evaluate the right-hand-side for the value. If the right-hand-side is another assignment, repeat... So given: int i = 0; int[] a = new int[4]; a[i++] = a[i+=2] = i = 9; You are can depend on getting: i = 9 a = [9, 0, 0, 9] D today on windows yields the same output. Will the D language spec make this the define behavior too? I noticed that http://www.digitalmars.com/d/2.0/expression.html currently says it is implementation defined. The example given is: i = i++; None of this is stuff you'd normally want to write unless entering an obfuscated programming contest, but Java's rules say if i = 42, 'i' will end up still being 42. DanOn 02/25/2011 05:09 PM, bearophile wrote: > int j; > int[2] y; > y[j] = j = 1; I think that's undefined behavior in C and C++. It is not defined whether j's previous or past value is used in y[j]. I would expect the situation be the same in D.No, that should be perfectly defined. What's undefined is when you do something like func(j, y[j]). The evaluation order of the function arguments is undefined. However, the evaluation order when dealing with an assignment should be defined. I _could_ be wrong about that, but there's no question that the assignments themselves are guaranteed to be done in right-to-left order. - Jonathan M Davis
Feb 26 2011
On Saturday 26 February 2011 11:18:20 Dan Olson wrote:Jonathan M Davis <jmdavisProg gmx.com> writes:The assignment order is well-defined in both C++ an D, but the order of=20 evaluation of the expressions is not. Now, Walter has stated in the past th= at he=20 intends to make the order of evaluation of expressions defined in D at some= =20 point, but he hasn't done it yet, so right now it's still undefined. Regardless, it doesn't really hurt you any to avoid ambiguous expressions l= ike=20 these and since there _are_ languages which leave ther evaluation order as= =20 undefined, it's probably a good habit to get into to _not_ write such ambig= uous=20 expressions. =2D Jonathan M DavisOn Friday, February 25, 2011 17:31:36 Ali =C7ehreli wrote:=20 Java made assignment well defined by saying: First evaluate the left-hand-side to determine a variable to assign to. Then evaluate the right-hand-side for the value. =20 If the right-hand-side is another assignment, repeat... =20 So given: int i =3D 0; int[] a =3D new int[4]; =20 a[i++] =3D a[i+=3D2] =3D i =3D 9; =20 You are can depend on getting: =20 i =3D 9 a =3D [9, 0, 0, 9] =20 =20 D today on windows yields the same output. Will the D language spec make this the define behavior too? I noticed that http://www.digitalmars.com/d/2.0/expression.html currently says it is implementation defined. The example given is: =20 i =3D i++; =20 None of this is stuff you'd normally want to write unless entering an obfuscated programming contest, but Java's rules say if i =3D 42, 'i' will end up still being 42.On 02/25/2011 05:09 PM, bearophile wrote: > int j; > int[2] y; > y[j] =3D j =3D 1; =20 I think that's undefined behavior in C and C++. It is not defined whether j's previous or past value is used in y[j]. =20 I would expect the situation be the same in D.=20 No, that should be perfectly defined. What's undefined is when you do something like func(j, y[j]). The evaluation order of the function arguments is undefined. However, the evaluation order when dealing with an assignment should be defined. I _could_ be wrong about that, but there's no question that the assignments themselves are guaranteed to be done in right-to-left order. =20 - Jonathan M Davis
Feb 26 2011
On 02/25/2011 04:56 PM, bearophile wrote:Is this program showing a bug in multiple assignments (DMD 2.052)? void main() { int i; int[2] x; i, x[i] = 1;I haven't heard about multiple assignments but that's the comma operator up there, separating (and sequencing) two expressions: 1) i 2) x[i] = 1assert(x == [1, 0]); // OK int j; int[2] y; y[j], j = 1;Again, two expressions: 1) y[j] 2) j = 1 Only the second of both cases have an effect. Aliassert(y == [0, 0]); // Not OK } At the end of the program I expect y to be [1,0] instead of [0,0]. Yet this C program with GCC: #include "stdio.h" int main() { int i = 0; int x[2] = {0, 0}; i, x[i] = 1; printf("%d %d\n", x[0], x[1]); int j = 0; int y[2] = {0, 0}; y[j], j = 1; printf("%d %d\n", y[0], y[1]); return 0; } has the same output as DMD: 1 0 0 0 Bye, bearophile
Feb 25 2011
On 02/26/2011 01:56 AM, bearophile wrote:Is this program showing a bug in multiple assignments (DMD 2.052)? void main() { int i; int[2] x; i, x[i] = 1; assert(x == [1, 0]); // OK int j; int[2] y; y[j], j = 1; assert(y == [0, 0]); // Not OK } At the end of the program I expect y to be [1,0] instead of [0,0].I'm far to be a C expert, but that looks like very normal C semantics, ain't it? with all its stupidity, indeed... I would enjoy an error in both cases. (not enough rvalues) Denis -- _________________ vita es estrany spir.wikidot.com
Feb 26 2011