From: Ersek, Laszlo on
In article <0.8e8fb4cfddc834871af3.20100307151405GMT.87hbos6u6a.fsf(a)bsb.me.uk>, Ben Bacarisse <ben.usenet(a)bsb.me.uk> writes:
> Rainer Weikusat <rweikusat(a)mssgmbh.com> writes:
>
>> Ben Bacarisse <ben.usenet(a)bsb.me.uk> writes:
>>> Rainer Weikusat <rweikusat(a)mssgmbh.com> writes:
>>>> pete <pfiland(a)mindspring.com> writes:
>>>>
>>>> [...]
>>>>
>>>>> To count down through an array with N elements, I use
>>>>>
>>>>> size_t i = N;
>>>>>
>>>>> while (i-- != 0) {
>>>>> array[i];
>>>>> }
>>>>
>>>> And you excuse for writing confusing code which requests that the
>>>> machine does useless things is that software to work around you has
>>>> already been developed, right?
>>>
>>> Why not show everyone what you consider to be the right way to do this
>>> so that we can all have the chance to write better/clearer loops? Not
>>> everyone will agree, of course, but it is surely better to give
>>> examples of good code than to criticise code you don't like.
>>
>> Isn't this obvious? As written above, the calculation oversteps,
>> because the postdecrement will return zero when i already had this
>> value before decrementing it again.
>
> What do you mean by "oversteps"? The code above works correctly when
> N is zero and it executes the body exactly N times as it should.


Yes, but after that, "i" ends up as (size_t)-1. Compare:

size_t i = N;

while (0u < i) {
--i;

array[i];
array[i];
array[i];
}

Cheers,
lacos
From: Ben Bacarisse on
lacos(a)ludens.elte.hu (Ersek, Laszlo) writes:

> In article <0.8e8fb4cfddc834871af3.20100307151405GMT.87hbos6u6a.fsf(a)bsb.me.uk>, Ben Bacarisse <ben.usenet(a)bsb.me.uk> writes:
>> Rainer Weikusat <rweikusat(a)mssgmbh.com> writes:
>>
>>> Ben Bacarisse <ben.usenet(a)bsb.me.uk> writes:
>>>> Rainer Weikusat <rweikusat(a)mssgmbh.com> writes:
>>>>> pete <pfiland(a)mindspring.com> writes:
>>>>>
>>>>> [...]
>>>>>
>>>>>> To count down through an array with N elements, I use
>>>>>>
>>>>>> size_t i = N;
>>>>>>
>>>>>> while (i-- != 0) {
>>>>>> array[i];
>>>>>> }
>>>>>
>>>>> And you excuse for writing confusing code which requests that the
>>>>> machine does useless things is that software to work around you has
>>>>> already been developed, right?
>>>>
>>>> Why not show everyone what you consider to be the right way to do this
>>>> so that we can all have the chance to write better/clearer loops? Not
>>>> everyone will agree, of course, but it is surely better to give
>>>> examples of good code than to criticise code you don't like.
>>>
>>> Isn't this obvious? As written above, the calculation oversteps,
>>> because the postdecrement will return zero when i already had this
>>> value before decrementing it again.
>>
>> What do you mean by "oversteps"? The code above works correctly when
>> N is zero and it executes the body exactly N times as it should.
>
> Yes, but after that, "i" ends up as (size_t)-1.

That's why I asked -- just in case this what his complaint. It's not
one I'd worry about. In fact in some situations this is an advantage:

> Compare:
>
> size_t i = N;
>
> while (0u < i) {
> --i;
>
> array[i];
> array[i];
> array[i];
> }

If the loop body changes so that is includes some break statements,
pete's loop makes normal and abnormal loop exit easy to distinguish.
It's not a big deal, but I do prefer pete's formulation for this
reason.

--
Ben.
From: Keith Thompson on
Rainer Weikusat <rweikusat(a)mssgmbh.com> writes:
> Ben Bacarisse <ben.usenet(a)bsb.me.uk> writes:
>> Rainer Weikusat <rweikusat(a)mssgmbh.com> writes:
>>> pete <pfiland(a)mindspring.com> writes:
>>>
>>> [...]
>>>
>>>> To count down through an array with N elements, I use
>>>>
>>>> size_t i = N;
>>>>
>>>> while (i-- != 0) {
>>>> array[i];
>>>> }
>>>
>>> And you excuse for writing confusing code which requests that the
>>> machine does useless things is that software to work around you has
>>> already been developed, right?
>>
>> Why not show everyone what you consider to be the right way to do this
>> so that we can all have the chance to write better/clearer loops? Not
>> everyone will agree, of course, but it is surely better to give
>> examples of good code than to criticise code you don't like.
>
> Isn't this obvious?

No -- or at least it's not nearly as obvious as you seem to think
it is.

> As written above, the calculation oversteps,
> because the postdecrement will return zero when i already had this
> value before decrementing it again.

It does, but I don't think this is a significant problem. The most
common form of loop for iterating *up* through an array is:

for (i = 0; i < N; i ++) [
... array[i] ...
}

oversteps the upper bound of the array.

> Also, the condition is known to be
> true so checking it before the first execution of the loop body is a
> pointless exercise.

That's true *only* if you know that you're iteratingover the entire
array. What if N, rather than being the total number of elements in
the array, is the number of elements that you're current interested
in? (Say you're working with a counted string implementation.)
Then N could easily be 0.

> A sensible way to express this in C would be
>
> do array[--i]; while (i);

This fails rather catastrophically when N is 0.

Do you use a different form of loop when N can be 0 vs. when you know
it can't? If not, can you show us a loop that (a) iterates from
size_t values N-1 down to 0, (b) is as efficient as pete's loop,
and (c) is as clear to the reader as pete's loop?

> This is politically incorrect for various reasons not the least one of
> which is that people are often proud of having written code
> thoughtlessly, presumably, because this demonstrate that it is below
> their dignity to care for something as miniscule as that, and which
> one will end up generating better code depends on the compiler and how
> it was used. Eg, I have reason to suspect that at least some versions
> of gcc transformate all loops to the 'condition in front of it'-form
> (I don't know the English term for this, the German one would be
> 'abweisende Schleife') before they are feed to the various weird loop
> optimizers intended to turn thoughtlessly written FORTRAN into
> sensible machine code.

There's a good reason for that. Very often a while or for loop
is the clearest way to express some algorithm. The body of the
loop might not be executed at all. So an optimizing compiler might
transform this:

while (condition) {
something;
}

to the equivalent of this:

if (condition) {
/* ... */
do {
something;
while condition;
}

Everything within the body of the loop is executed N times, for
some N >= 0. If some of that code is loop-invariant, it can be
executed just once -- but if N is 0, it shouldn't be executed
at all. Loop-invariant code can be "hoisted" outside the loop.
The purpose of the transformation is to provide a place (marked
/* ... */) to which any loop-invariant code can be hoisted.

This *doesn't* imply that the programmer should have written the
if/do while version of the code in the first place. The while loop
is generally clearer to the reader than the transformed version,
and easier to maintain since the condition is only written once.
It requires the optimizer to do a tiny amount of extra work, but
that's its job.

[snip]

Our fundamental point of disagreement is that you seem to think
that pete's loop:

size_t i = N;

while (i-- != 0) {
array[i];
}

is not merely bad, but obviously bad, whereas I see nothing wrong
with it. The initial test is superfluous only if we know that N
> 0; I don't think leaving it in place is a significant problem,
worth restructuring the code. i is incremented again at the end,
leaving it with a value if SIZE_MAX after the loop; again, I don't
think that's a significant problem.

Indeed, if C had a higher-level loop construct for iterating over a
range of values:

for i in reverse 0 .. N-1 loop
...
end loop;

(that's Ada syntax), the compiler might well generate exactly the
same code as it does for pete's loop.

--
Keith Thompson (The_Other_Keith) kst-u(a)mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
From: Ersek, Laszlo on
In article
<0.487c45f99df6405ef9e4.20100307192325GMT.87iq98542a.fsf(a)bsb.me.uk>,
Ben Bacarisse <ben.usenet(a)bsb.me.uk> writes:

> lacos(a)ludens.elte.hu (Ersek, Laszlo) writes:
>
>> In article
>> <0.8e8fb4cfddc834871af3.20100307151405GMT.87hbos6u6a.fsf(a)bsb.me.uk>,
>> Ben Bacarisse <ben.usenet(a)bsb.me.uk> writes:

>>> Rainer Weikusat <rweikusat(a)mssgmbh.com> writes:
>>>
>>>> Ben Bacarisse <ben.usenet(a)bsb.me.uk> writes:
>>>>> Rainer Weikusat <rweikusat(a)mssgmbh.com> writes:
>>>>>> pete <pfiland(a)mindspring.com> writes:
>>>>>>
>>>>>>> To count down through an array with N elements, I use
>>>>>>>
>>>>>>> size_t i = N;
>>>>>>>
>>>>>>> while (i-- != 0) {
>>>>>>> array[i];
>>>>>>> }

>> size_t i = N;
>>
>> while (0u < i) {
>> --i;
>>
>> array[i];
>> array[i];
>> array[i];
>> }
>
> If the loop body changes so that is includes some break statements,
> pete's loop makes normal and abnormal loop exit easy to distinguish.
> It's not a big deal, but I do prefer pete's formulation for this
> reason.

Yeah... I was thinking, "who will be the first one to say 'linear
search'?" :) "0u == i" doesn't say anything after the loop.

Cheers,
lacos
From: Rainer Weikusat on
Keith Thompson <kst-u(a)mib.org> writes:
> Rainer Weikusat <rweikusat(a)mssgmbh.com> writes:
>> Ben Bacarisse <ben.usenet(a)bsb.me.uk> writes:
>>> Rainer Weikusat <rweikusat(a)mssgmbh.com> writes:
>>>> pete <pfiland(a)mindspring.com> writes:
>>>>
>>>> [...]
>>>>
>>>>> To count down through an array with N elements, I use
>>>>>
>>>>> size_t i = N;
>>>>>
>>>>> while (i-- != 0) {
>>>>> array[i];
>>>>> }
>>>>
>>>> And you excuse for writing confusing code which requests that the
>>>> machine does useless things is that software to work around you has
>>>> already been developed, right?
>>>
>>> Why not show everyone what you consider to be the right way to do this
>>> so that we can all have the chance to write better/clearer loops? Not
>>> everyone will agree, of course, but it is surely better to give
>>> examples of good code than to criticise code you don't like.
>>
>> Isn't this obvious?
>
> No -- or at least it's not nearly as obvious as you seem to think
> it is.

It is completely obvious from the difference of meaning of the code
which was written down vs the part of the code which actually performs
some sensible function. Spelled out, the condition means (assuming
that x is also a variable of type size_t)

x = i, i = i - 1, x != 0

Since the loop is only supposed to run until the counter has reached
the value zero, decrementing an i whose value is zero when the
condition is checked for the last time is just a pointless contortion.


>> As written above, the calculation oversteps,
>> because the postdecrement will return zero when i already had this
>> value before decrementing it again.
>
> It does, but I don't think this is a significant problem.

If you desire to argue against my position, why don't you do so? I
explained why I consider this to be a serious problem in the text
below.

> The most
> common form of loop for iterating *up* through an array is:
>
> for (i = 0; i < N; i ++) [
> ... array[i] ...
> }
>
> oversteps the upper bound of the array.

So, your reasoning goes roughly "well, ok, it is nonsense, but that's
what we always do". That you always write code which requests that
superflouus calculations are performed is no reason why doing so
should be desirable.

>> Also, the condition is known to be
>> true so checking it before the first execution of the loop body is a
>> pointless exercise.
>
> That's true *only* if you know that you're iteratingover the entire
> array.

This is always true for the context the text which was following this
statement was supposed to make sense in. It doesn't matter what over
contexts you can dream up. That was the one I was using. Call it 'a
precondition' if you like.

[...]

>> A sensible way to express this in C would be
>>
>> do array[--i]; while (i);
>
> This fails rather catastrophically when N is 0.

It fails even more catastrophically when i was initially zero and
traversing the array in order of ascending indices was intended and
yet more catastrophically when, instead of traversing an array, the
string "Are you perhaps resorting to sophististry because you don't
have any arguments for your position" should have been printed. But
since none if this is/ was the case, that's quite besides the point.

If you desire to address the point I was trying to make, feel free to
do so. These sideline battles are useless exercises.

First  |  Prev  |  Next  |  Last
Pages: 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
Prev: integer
Next: shared memory question