Faster for() loops?

M

Mark McIntyre


For what its worth, arguments based on threading are bunk. Thread
members arrive out-of-order, not at all, and disappear from servers.

And arguments based on catering for cretinous users who're too thick
to snip are hardly likely to impress smart people...

I slightly agree with your conclusions tho. I'd modify (1) and (2) as
follows

1) Top Post (and totally remove the old message) if you are only
making 1 brief point which has no relation to any of the old message.
And then ask yourself why the hell you're replying to this post with
an irrelevant remark.

2) otherwise middle post
 
R

Richard Henry

Dave Hansen said:
FWIW, my bit-bang SPI output function looks something like

bit_ctr = 8;
do
{
Set_IO(SPI_DATA, (data&0x80) != 0);
Set_IO(SPI_CLOCK, 1);
data <<= 1;
Set_IO(SPI_CLOCK, 0);

} while (--bit_ctr);

which seems intuitive for the function at hand, and generates nearly
optimal assembly on all the platforms it's used on.

A little alarm goes off in my brain every time I see an arithmetic variable
(bit_ctr) used as the parameter of a logical expression (while).

The following line better expresses what I think you mean:
while (--bit_ctr != 0);

The compiler optimizer may well deliver the same machine code for both
methods.

And please don't let me get started with the use of NULL pointers in similar
situations.
 
T

toby

Joe said:
What if the difference is between fitting into memory and not?

The answer to that is the same remedy offered to all sufferers of
premature optimisation: Measure First.
 
T

toby

David said:
..."Use
word-size variables instead of chars" (great for PPC, indifferent for
msp430, terrible for AVR),

Catastrophic for PIC18.
"Addition is faster than multiplication - use
'val + val + val' instead of 'val * 3' " (wrong for most compiler/target
combinations).

And the implication is especially wrong for any val*n where n>3.

--T
 
K

Keith Thompson

Mark McIntyre said:
I slightly agree with your conclusions tho. I'd modify (1) and (2) as
follows

1) Top Post (and totally remove the old message) if you are only
making 1 brief point which has no relation to any of the old message.
And then ask yourself why the hell you're replying to this post with
an irrelevant remark.

Top-posting is posting new text *above* any quoted text; if there is
no quoted text, it's not top-posting (or at best it's a degenerate
case that could as easily be called bottom-posting or middle-posting).
What you're describing is, or should be, simply posting a new article.
 
K

Keith Thompson

Richard Henry said:
A little alarm goes off in my brain every time I see an arithmetic variable
(bit_ctr) used as the parameter of a logical expression (while).

The following line better expresses what I think you mean:
while (--bit_ctr != 0);

The compiler optimizer may well deliver the same machine code for both
methods.

And please don't let me get started with the use of NULL pointers in similar
situations.

I tend to agree, in that I try to use only expressions that are
logically Boolean values as conditions, adding an explicit comparison
for anything else. But things like "while (--bit_ctr)", "if (ptr)",
and "if (!ptr)" are common C idioms. You might consider disconnecting
the little alarm in your brain, or at least turning down the volume.
The set of C code that you can easily read should be much wider than
the set of C code that you'd be willing to write.
 
C

Christian Bau

"Richard Henry said:
A little alarm goes off in my brain every time I see an arithmetic variable
(bit_ctr) used as the parameter of a logical expression (while).

The following line better expresses what I think you mean:
while (--bit_ctr != 0);

The compiler optimizer may well deliver the same machine code for both
methods.

And please don't let me get started with the use of NULL pointers in similar
situations.

Well, if anyone writes code like

then they will get what they deserve!
 
R

Richard Henry

Keith Thompson said:
I tend to agree, in that I try to use only expressions that are
logically Boolean values as conditions, adding an explicit comparison
for anything else. But things like "while (--bit_ctr)", "if (ptr)",
and "if (!ptr)" are common C idioms. You might consider disconnecting
the little alarm in your brain, or at least turning down the volume.
The set of C code that you can easily read should be much wider than
the set of C code that you'd be willing to write.

I read it ok. I can see that it will work. But when I encounter these
situations, I just stop to think "What will happen here? How can this go
wrong?"
 
T

toby

Christian said:
...
Well, if anyone writes code like


then they will get what they deserve!

Do you really think

for( p = /*whatever*/ ; p ; --p ){
/*somestuff*/
}

is any better?

Of course, the idea of counting a *pointer* down to NULL is rather
implausible in real code. Maybe you intended an integer variable.
 
S

Skarmander

toby said:
Do you really think

for( p = /*whatever*/ ; p ; --p ){
/*somestuff*/
}

is any better?

Of course, the idea of counting a *pointer* down to NULL is rather
implausible in real code. Maybe you intended an integer variable.
Hold on there. Is there any guarantee that any amount of -- applications
eventually yield a null pointer? Could this loop forever or does it
summon nasal demons?

S.
 
T

toby

Skarmander said:
Hold on there. Is there any guarantee that any amount of -- applications
eventually yield a null pointer? Could this loop forever or does it
summon nasal demons?

It's not guaranteed by the standard but on all implementations I know
of, it will eventually get there, unless of course, p isn't a multiple
of sizeof(*p) to begin with ;-) -- which can only arise through
naughtiness anyway.
 
T

toby

toby said:
It's not guaranteed by the standard but on all implementations I know
of, it will eventually get there, unless of course, p isn't a multiple
of sizeof(*p) to begin with ;-) -- which can only arise through
naughtiness anyway.

....Or unless a runtime exception (such as alignment or protection
fault) intervenes.
 
K

Keith Thompson

I suspect, based on his "then they will get what they deserve!", that
he really was referring to counting down a pointer.
It's not guaranteed by the standard but on all implementations I know
of, it will eventually get there, unless of course, p isn't a multiple
of sizeof(*p) to begin with ;-) -- which can only arise through
naughtiness anyway.

It's more than "not guaranteed by the standard". Repeatedly
decrementing a pointer will invoke undefined behavior as soon as the
location it points to is no longer within the original object. It may
happen to "work" on many systems; such is the nature of undefined
behavior.

Incidentally, there's no requirement for p to be a multiple of
sizeof(*p) (unless sizeof(*p)==1, of course). If the designated type
is sufficiently large, its required alignment is almost certainly
smaller than its size (1024-byte structures don't have to be aligned
on 1024-byte boundaries). Even for smaller types, alignment
requirements are system-specific; there's nothing non-conforming about
allowing 2-byte or 4-byte integers to be allocated on odd addresses.
 
S

Steve at fivetrees

Richard Henry said:
A little alarm goes off in my brain every time I see an arithmetic
variable
(bit_ctr) used as the parameter of a logical expression (while).

The following line better expresses what I think you mean:
while (--bit_ctr != 0);

Whoa. As others have observed, --value/value-- as a boolean test is a common
idiom in C - check K&R's version of strcpy for an example.

There comes a point where one can be *too* explicit. I remember arguing over
a coding standards document with someone who insisted that all boolean tests
should be tested for equality with TRUE or FALSE (previously defined in
their own pet/preferred fashion, of course) - hence:

if ( boolean_flag == TRUE )

where I would have argued that:

if ( boolean_flag )

was safer, since it didn't depend on a specific value of TRUE. I pointed out
that his argument could be extended to:

if (((( boolean_flag == TRUE ) == TRUE ) == TRUE ) == TRUE ) // etc

which seemed dumb to me. He didn't understand the point.
And please don't let me get started with the use of NULL pointers in
similar
situations.

That's a whole different situation, and not relevant/applicable to the
above.

Steve
http://www.fivetrees.com
 
S

Skarmander

Steve at fivetrees wrote:
There comes a point where one can be *too* explicit. I remember arguing over
a coding standards document with someone who insisted that all boolean tests
should be tested for equality with TRUE or FALSE (previously defined in
their own pet/preferred fashion, of course) - hence:

if ( boolean_flag == TRUE )

where I would have argued that:

if ( boolean_flag )

was safer, since it didn't depend on a specific value of TRUE.

Yeah. Provided TRUE wasn't defined as, you know, 0. Of course you'd have
to be stupid or perverse to do that. But you did say "defined in their
own pet/preferred fashion".
I pointed out that his argument could be extended to:

if (((( boolean_flag == TRUE ) == TRUE ) == TRUE ) == TRUE ) // etc

which seemed dumb to me. He didn't understand the point.
<snip>
Probably because (boolean_flag == TRUE) invokes == to yield a "C
boolean", which is by definition good to go in an if statement. No
further comparison necessary.

Mind you, I'm not encouraging or defending any of this. I'm not willing
to go any further than
typedef enum {false, true} bool;
But then, better use #define, or otherwise everything will break when
someone else defines the exact same enum. Sigh...

This is why I usually stick to 0, 1, and remembering when an int is used
as a pure boolean. "Extending" the language this way isn't worth it.
C99's bool is way overdue, but at least it's there.

S.
 
R

Richard Henry

Steve at fivetrees said:
Whoa. As others have observed, --value/value-- as a boolean test is a common
idiom in C - check K&R's version of strcpy for an example.

There comes a point where one can be *too* explicit. I remember arguing over
a coding standards document with someone who insisted that all boolean tests
should be tested for equality with TRUE or FALSE (previously defined in
their own pet/preferred fashion, of course) - hence:

if ( boolean_flag == TRUE )

where I would have argued that:

if ( boolean_flag )

was safer, since it didn't depend on a specific value of TRUE. I pointed out
that his argument could be extended to:

if (((( boolean_flag == TRUE ) == TRUE ) == TRUE ) == TRUE ) // etc

which seemed dumb to me. He didn't understand the point.


That's a whole different situation, and not relevant/applicable to the
above.

The use of a boolean flag as the target parameter of a boolean expression is
of course completely appropriate. What I was whining about (I admit it is a
pointless whine) was using an arithmetic object, as in if(--index). What
that really means is "if the decremented index now equals 0" and just takes
advantage of the fact that the if operator (or while operator) in C is
hinged on the 0 value (from the ubiquitous JMPZ (or similar) operator, I
would suppose). While it is correct in C grammar, and will "always work",
it is not clear what you mean by that. The longer statement if(--index ==
0) (or in better style, if (0 == --index)) gets the same result, possible in
the same amount of machine code, and is explicit about its meaning.

As for pointers: I was not talking about decrementing pointers, but their
use in while( and if( statements as above. When you write

if(ptr)
{
//do something
}

what you really mean is

if(ptr != NULL)
{
//do something
}
 
J

Jim Granville

Steve said:
Whoa. As others have observed, --value/value-- as a boolean test is a common
idiom in C - check K&R's version of strcpy for an example.

There comes a point where one can be *too* explicit. I remember arguing over
a coding standards document with someone who insisted that all boolean tests
should be tested for equality with TRUE or FALSE (previously defined in
their own pet/preferred fashion, of course) - hence:

if ( boolean_flag == TRUE )

where I would have argued that:

if ( boolean_flag )

was safer, since it didn't depend on a specific value of TRUE.
<snip>

I'd agree the TRUE and FALSE instance are pedantic, but THIS form

if ( boolean_flag == RlyON )

can be safer and simpler, as any downstream logic inversion is
handled transparently.
Here, you have a common define setting RlyON is active Hi or Lo,
but the code is always clearer. ( and that may change with
PCB revision, for example )

Also note that not all compilers treat these the same !!

if ( boolean_flag == TRUE )
if ( boolean_flag )

-jg
 
C

Chris Torek

And sometimes the intermediates go missing entirely.

As in this case.

(Which, I admit, I faked. :) But I have read followups to which
the ancestor was missing, and in many cases, the followup was
incomprehensible as a result.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top