I
Ian Collins
Can you provide an example?Frederick said:Keith Thompson posted:
Efficiency and clarity. And efficiency again.
Can you provide an example?Frederick said:Keith Thompson posted:
Efficiency and clarity. And efficiency again.
Frederick said:Keith Thompson posted:
If my own opinion is worth anything, I've never used NULL once in my code.
Frederick said:Flash Gordon posted:
I would frown upon the use of array subscripting rather than pointers.
Frederick said:Keith Thompson posted:
If my own opinion is worth anything, I've never used NULL once in my code.
Just a *few* suggestions:
You're executing TWO assignment statements unecessarily in the case
where one or both params are NULL. And you neednt set "j" at all
here, as it's always set in the for initializer part (whatever you call
the first for() thingamaggummy).
You are to be complimented n checking your parameters, wish MicroSoft
did so with any regularity in their examples.
But would it kill you to write clearer code, ala:
if( a == NULL || b == NULL ) ....
Yes, I know !a is a well established C idiom. Even highly regarded
snippets of code are full of that kind of thing. Pls ponder the
relative clarity of each, especially when you get a call at 2:21AM to
fix your program.
"return" is a mighty hand thing, but it's in a sense a amorphous goto.
Consider having just one exit point, at the bottom of the function. It
makes adding debug lines, assertions, and return value settings sooo
much clearer.
for(;a;i++)
This is fine, a really puristt would suggest initializing "i" here,
just in case someone ever adds code between the initialization and this
point and one loses track of wat's in "i".
Also a bubbly-headed coder might suggest "a != EndOfString" or even
"a IsNot EndOfString". Much clearer when the F133 payroll program
for the whole Skunk Works Division of Lockheed isnt running (a friend
of mine was called at 4 AM to fix that).
Yes, it takes a smidgen more typing, but disk space is not exactly
expensive these days.
To OP: Don't be so miserly on spaces!Otherwise okay.
Ancient_Hacker said:Just a *few* suggestions:
You're executing TWO assignment statements unecessarily in the case
where one or both params are NULL.
And you neednt set "j" at all here,
But would it kill you to write clearer code, ala:
if( a == NULL || b == NULL ) ....
Yes, I know !a is a well established C idiom. Even highly regarded
snippets of code are full of that kind of thing. Pls ponder the
relative clarity of each, especially when you get a call at 2:21AM to
fix your program.
"return" is a mighty hand thing, but it's in a sense a amorphous goto.
Consider having just one exit point, at the bottom of the function.
for(;a;i++)
Also a bubbly-headed coder might suggest "a != EndOfString" or even
"a IsNot EndOfString".
Frederick Gotham said:main() posted:
You should decide whether you want the programmer to be able to supply this
function with null pointers. If you forbid this, then use assertions:
assert(a);
assert(b);
Can you provide an example?
Using arrays rather than pointers is often clearer
and also often produces faster code. If you measure
you may find yourself giving up some of your ideas
about which choice is better.
How do you terminate your lists?
Microsoft does so many things absolutely wrong that having M$ as
excample makes no sense except as bad one.
Boa, ey! Not anybody is a beginner like you who can't read and
understund most common used style. As sayed above: don't bother on
style.
Pls ponder the relative clarity of each, especially when you get a call
at 2:21AM to fix your program.
While developing only! Do not, ever, let a user see the result of an
assertion failure. They get remarkably stroppy when all their work is
dumped in the bit bucket with nothing to show for it but a cryptic error
message, and that for no better reason than that the programmer was too
lazy to use proper error checking instead of assert(). NDEBUG is your
friend, here.
Frederick said:Bill Pursell posted:
I don't understand the question, please be more specific.
Frederick said:Ian Collins posted:
Can you provide an example?
Firstly, let's take two snippets which achieve the same objective:
Snippet (1):
size_t i;
for(i = 0; i != len; ++i)
{
arr += 77;
}
Snippet (2):
int *p = arr;
int const *const pover = arr + len;
do *p++ += 77;
while(p != pover);
The body of the loop in Snippet (1) is equivalent to:
*(arr + i) += 77;
Upon each iteration, "i" is added to the address of the first element, and
then this address is dereferenced and assigned to.
Looking at the body of the loop in Snippet (2), "p" is dereferenced and
assigned to, and then "p" is incremented.
Snippet (2) is more efficent,
> and is cleaner in my opinion -- I much prefer
incrementing pointers than playing around with array indexes (but maybe
this is a matter of personal taste).
Of course, an optimising compiler *might* produce the same code for both,
but I prefer Snippet (2), as I like to write efficient code, and I also
think it's cleaner.
Frederick said:posted:
I don't see how array subscripting could be faster. Elsethread, I have
explained how the pointer version is likely to be faster.
Can you give an example of where array subscripting would be faster for
iterating through an array?
You are assuming that the optimiser does not convert both to the same
machine code. You are also assuming that the processor does not have
index operations which would make the array form require only one
instruction or that said machine code instructions are slower.
It isn't necessarily more efficient even if converted directly in to
assembler with no optimisation. Personally I would bin any compiler so
bad it could not reduce array operations to pointer operations if the
pointer version was more efficient.
As other have pointed out it can be *harder* for the compiler to
optimise pointer operations because it has to be able to prove whether
aliasing is occurring or not.
The best rule is to always write what you consider to be clearest, not
what you think might save a fraction off the execution time. Since you
consider the pointer version to be clearer *that* is a valid reason for
preferring the pointer versions, but when someone considers the array
index version to be clearer there is nothing intrinsically wrong with
it.
size_t my_strlen_array( const char *s ){
unsigned r = 0;
while (s[r]) r++;
return r;
}
size_t my_strlen_pointer( const char *s ){
unsigned r = 0;
while (*s++) r++;
return r;
}
size_t my_strlen_pointer_2( const char *const s_0 ){
const char *s = s_0;
while (*s) s++;
return s-s_0;
}
My measurements show my_strlen_array is faster than
either of the pointer versions. YMMV, of course.
There are other ways to implement this, of course, but
the most natural is to use NULL as the terminator.
Frederick said:Ian Collins posted:
Can you provide an example?
Firstly, let's take two snippets which achieve the same objective:
Snippet (1):
size_t i;
for(i = 0; i != len; ++i)
{
arr += 77;
}
Snippet (2):
int *p = arr;
int const *const pover = arr + len;
do *p++ += 77;
while(p != pover);
The body of the loop in Snippet (1) is equivalent to:
*(arr + i) += 77;
Upon each iteration, "i" is added to the address of the first element, and
then this address is dereferenced and assigned to.
Looking at the body of the loop in Snippet (2), "p" is dereferenced and
assigned to, and then "p" is incremented.
Snippet (2) is more efficent, and is cleaner in my opinion -- I much prefer
incrementing pointers than playing around with array indexes (but maybe
this is a matter of personal taste).
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.