Chuck Guzis wrote:
On 8/13/2006 at 11:53 PM Sean Conner wrote:
for (i = 0 ; i < MAX ; i++)
foo[i] = 0;
when it could easily be replaced with:
memset(foo,0,sizeof(foo));
The argument some would give you is that if you had a compiler worth spit,
it would optimize away the index and reduce the above to:
memset(foo,0,sizeof foo);
i = MAX;
Then if the compiler saw that the value of i was re-initialized without
being read, it would get rid of the last statement. The explicit loop
statement is a easy way to explicitly state what's meant and does not rely
on the implementation of a library function.
Never trust an optimization unless you see it for yourself.
Looking at a real-world example of generated code, I wrote
#include <string.h>
extern char x1[1024];
extern char x2[1024];
void clear()
{
// For loop
for (int i = 0; i < 1024; i++)
{
x1[i] = 0;
}
// memset
memset(x2, 1, 1024);
}
x1 and x2 were declared external so that the optimizer won't optimize
references to them away.
This generated the following output using O3 level optimization
[kevin at kevin temp]$ gcc --version
gcc (GCC) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)
Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There
is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.
[kevin at kevin temp]$ gcc -S -O3 -std=c99 opt.c
[kevin at kevin temp]$ cat opt.s
.file "opt.c"
.text
.p2align 2,,3
.globl clear
.type clear, at function
clear:
pushl %ebp
movl %esp, %ebp
xorl %eax, %eax
subl $8, %esp
.p2align 2,,3
.L6:
movb $0, x1(%eax) ; ** for loop
incl %eax
cmpl $1023, %eax
jle .L6
pushl %eax ; **memset
pushl $1024
pushl $1
pushl $x2
call memset
leave
ret
.Lfe1:
.size clear,.Lfe1-clear
.ident "GCC: (GNU) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)"
So, in this case the loop operates inline, while the memset
version pushes parameters onto the stack, then calls an
external function.
I suspect that the loop version, which generates inline code with
hardwired values, is likely to be slightly faster than the call to
memset, unless memset is doing something very odd.
gcc 4.1.2 generates similiar, but different code. memset still
calls an external routine.
One thing I've learned is "never underestimate
the cleverness of a good
optimizer". If a loop is particularly complicated, you can occasionally
find an automatic optimization that's nothing short of pure genius.
We need to ask more of our compiler writers; we really do.
That's just the programmer not knowing the
available functions, or
perhaps, coming from a system that doesn't have stat() available (it's not
part of the ANSI-C standard library, limiting the ways one can get the
size
of a file portably, and each of them having
problems). For more horror
stories, you can always check out
http://thedailywtf.com/ .
Why not fseek( file, 0, SEEK_END); length = ftell( file); ?
ANSI-compatible and shouldn't involve any I/O.
Which doesn't generate accurate values on VMS.