Jump to page: 1 2
Thread overview
"a[++i] = i" vs "a[i] = ++i"
Dec 20, 2013
Ivan Smirnov
Dec 20, 2013
Ali Çehreli
Dec 20, 2013
bearophile
Dec 20, 2013
aldanor
Dec 21, 2013
bearophile
Dec 21, 2013
aldanor
Dec 21, 2013
Dicebot
Dec 21, 2013
aldanor
Dec 21, 2013
bearophile
Dec 23, 2013
David Held
Dec 24, 2013
Charles Hixson
Dec 24, 2013
David Held
Dec 24, 2013
monarch_dodra
Dec 24, 2013
Timon Gehr
Dec 24, 2013
H. S. Teoh
Dec 24, 2013
Timon Gehr
Dec 24, 2013
H. S. Teoh
Dec 24, 2013
Timon Gehr
Dec 20, 2013
H. S. Teoh
December 20, 2013
I was wondering if this behavior is actually documented anywhere? Let's say we want to increment i and store the new value at the index equal to the new (incremented) value.

	int[int] a;
	int i = 1;
	a[++i] = i;
	writeln(a);
	a[i] = ++i;
	writeln(a);

>> [2:2]
>> [2:2, 3:3]

If any, I would expect it to work for either one of lines but not both?

What is interesting, if you compile the same in C (I used clang), you get a "warning: unsequenced modification and access to 'i'" on both lines and the answer is (as I would initially except)

>> [2:1]
>> [2:1, 3:3]
December 20, 2013
On 12/20/2013 02:29 PM, Ivan Smirnov wrote:> I was wondering if this behavior is actually documented anywhere? Let's
> say we want to increment i and store the new value at the index equal to
> the new (incremented) value.
>
>      int[int] a;
>      int i = 1;
>      a[++i] = i;
>      writeln(a);
>      a[i] = ++i;
>      writeln(a);
>
>>> [2:2]
>>> [2:2, 3:3]
>
> If any, I would expect it to work for either one of lines but not both?
>
> What is interesting, if you compile the same in C (I used clang), you
> get a "warning: unsequenced modification

That is a roundabout way of saying "the assignment operator does not define a sequence point". :p

> and access to 'i'" on both
> lines and the answer is (as I would initially except)
>
>>> [2:1]
>>> [2:1, 3:3]

Well, regardless of one's expectations, that is one outcome of unspecified behavior. :)

Although D is less vocal on these topics it is the same as C and C++: The evaluation order is unspecified. I've read before that Walter wants to eventually define such evaluation orders but it is not specified yet.

Ali

December 20, 2013
On Fri, Dec 20, 2013 at 11:29:54PM +0100, Ivan Smirnov wrote:
> I was wondering if this behavior is actually documented anywhere? Let's say we want to increment i and store the new value at the index equal to the new (incremented) value.
> 
> 	int[int] a;
> 	int i = 1;
> 	a[++i] = i;
> 	writeln(a);
> 	a[i] = ++i;
> 	writeln(a);
[...]

In C/C++, the evaluation order in this case is unspecified, so you're in the territory of undefined behaviour. Whatever you observe will be specific to the compiler (and version) you're using, and you cannot depend on getting the same result across different compilers (or even different versions of the same compiler, or even different compiler flags -- using -O may change the behaviour in some cases).

Now, in D, I believe this is currently also undefined behaviour, although Walter did mention at some point that he wanted to fix evaluation order in these cases. But I don't know if that has happened yet. Either way, you're treading on dangerous ground, since the spec currently doesn't say one way or another, so different compilers could have different interpretations of what the above code means. So the runtime behaviour could change from compiler to compiler, or from version to version, or from specifying -O or not.

Mixing side-effects in an expression that references the changed value multiple times should be avoided in general because of these kinds of ambiguity. For example, what should the following code do?

	int a = 1;
	int b = ++a * --a + --a * ++a;

(N.B. * must be evaluated before +. So does ++/-- get evaluated before or after *, or something else?)


T

-- 
Государство делает вид, что платит нам зарплату, а мы делаем вид, что работаем.
December 20, 2013
Ali Çehreli:

> Although D is less vocal on these topics it is the same as C and C++: The evaluation order is unspecified. I've read before that Walter wants to eventually define such evaluation orders but it is not specified yet.

Right, currently the outcome of that kind of code is not specified in D. So writing it is a error, and the D compiler doesn't warn you. Do not write that kind of code in D.

Walter wants to eventually (but when? Five years from now?) make that code specified, this means all the D compilers will know what that kind of code produce and will all give the same result reliably.

But in my opinion making the code unambiguous and specified for the compiler is not enough. You have also to take in account people that write and read the code, it needs to be unambiguous for them too. For them that kind of code can become tricky, even when you know the rules used by the compiler. So I'd like that kind of D code just to be disallowed, to be an error (and this doesn't break compatibility with C, because equivalent C code is not defined).

Bye,
bearophile
December 20, 2013
On Friday, 20 December 2013 at 23:17:31 UTC, bearophile wrote:

> Right, currently the outcome of that kind of code is not specified in D. So writing it is a error, and the D compiler doesn't warn you. Do not write that kind of code in D.
>
> Walter wants to eventually (but when? Five years from now?) make that code specified, this means all the D compilers will know what that kind of code produce and will all give the same result reliably.
>
> But in my opinion making the code unambiguous and specified for the compiler is not enough. You have also to take in account people that write and read the code, it needs to be unambiguous for them too. For them that kind of code can become tricky, even when you know the rules used by the compiler. So I'd like that kind of D code just to be disallowed, to be an error (and this doesn't break compatibility with C, because equivalent C code is not defined).
I completely agree.

I guess my point is, it would be nice if the compiler (at least) fired a warning about this kind of things, kinda of like clang does for both statements (and rightly so). It is nigh impossible for a D newcomer figure out if this kind of code is valid or not, and as you can see from the random example above one might think that it is indeed the way to go.
December 21, 2013
aldanor:

> it would be nice if the compiler (at least) fired a warning about this kind of things,

For reasons D doesn't like warnings, they are kept at a minimum. D prefers errors :-)

Bye,
bearophile
December 21, 2013
On Saturday, 21 December 2013 at 01:00:48 UTC, bearophile wrote:
> aldanor:
>
>> it would be nice if the compiler (at least) fired a warning about this kind of things,
>
> For reasons D doesn't like warnings, they are kept at a minimum. D prefers errors :-)
>
> Bye,
> bearophile

So.. isn't it exactly the case where a warning is most suitable? :) C/C++ compilers sure get it right in this regard.
December 21, 2013
On Saturday, 21 December 2013 at 02:52:26 UTC, aldanor wrote:
> So.. isn't it exactly the case where a warning is most suitable? :) C/C++ compilers sure get it right in this regard.

No. There is no such thing as "suitable compiler warning".

It should have been an error.
December 21, 2013
On Saturday, 21 December 2013 at 02:56:57 UTC, Dicebot wrote:
> No. There is no such thing as "suitable compiler warning".

So should this considered a bug then and be filed? (if that will do any good, lol)
December 21, 2013
aldanor:

> So should this considered a bug then and be filed?

I think so. I have a related EnhancementRequest open, but I have to close it down or modify it...

Bye,
bearophile
« First   ‹ Prev
1 2