这是我的页面头部

gcc 中 -O选项对空函数的优化

将空函数优化掉是一项很有意义的工作。比如,在程序中,常常要定义一个打印函数。如果在 release时,把这个函数使用条件编译定义为空函数。

 

且此空函数被优化掉,那就可以极大地提高程序的性能。

 

测试表明: 在gcc中,使用 -O可以优化掉内联的空函数。默认情况下,空函数不会被优化掉。即使使用 -O,也不会优化掉非内联的空函数。

内联的空函数会被优化掉是很容易理解的。函数被内联后,没有了参数入栈出栈操作,自然也就无代码可生成了。

但没有优化选项是,内联函数不会被优化,我却想不通。既然 声明为 inlinne,为什么函数没有被优化掉。那还要 inline何用?

下面分别是c源文件, 未优化的汇编代码,优化后的汇编代码。

// source code empty.c


inline void dbg( const char* s )
{
};
int main()
{
for( int i = 0; i < 10 ; i ++ )
{
dbg( "hello!" );
}
return 0;
}

/* assembler code generated by gcc 3.2.3 on redhat platform
env: GCC: (GNU) 3.2.3 20030502 (Red Hat Linux 3.2.3-47.3)
cmd: $ gcc -S -masm=intel -O emptyfun.c -o noopt.asm

*/


main:
push %ebp
mov %ebp, %esp
sub %esp, 8
and %esp, -16
mov %eax, 0
sub %esp, %eax
mov DWORD PTR [%ebp-4], 0 ;
.L3: ; for( ; ; ; )
cmp DWORD PTR [%ebp-4], 9 ; if ( i > 9 )
jle .L6 ; {
jmp .L4 ; break;
.L6: }
sub %esp, 12 ; //为 dbg()分配栈空间
push OFFSET FLAT:.LC0 ; //参数 "hello!" 压栈
call dbg ; dbg( "hello!" );
add %esp, 16 ; // 平栈
lea %eax, [%ebp-4]
inc DWORD PTR [%eax] ; i++;
jmp .L3
.L4:
mov %eax, 0
leave
ret

/*assembler code generated by gcc 3.2.3 with -O opition on redhat platform
env: GCC: (GNU) 3.2.3 20030502 (Red Hat Linux 3.2.3-47.3)
cmd: $ gcc -S -masm=intel -O emptyfun.c -o opt.asm */


main:
push %ebp
mov %ebp, %esp
sub %esp, 8
and %esp, -16
mov %eax, 0 ; i = 0;
.L7: ; for( ; ; ; )
inc %eax ; { i++;
cmp %eax, 9 ; ( if i <=9 )
jle .L7 ; continue;
mov %eax, 0 ; }
leave
ret
 
以下代码完成了 打印错误消息的功能:


#include 
<stdio.h>

#include 
<stdlib.h>

#include 
<unistd.h>

#include 
<limits.h>

#include 
<errno.h>

#include 
<stdarg.h>

#define MAXLINE 2048

#define DEBUG



/*

 err_doit 将用户指定的字串和系统错误信息打印到指定的文件

 fileno 文件号

 error  用户定义字串





*/

static void

err_doit(
int fileno, int error, const char *fmt, va_list ap)

{

    
char    buf[MAXLINE];

    
int msglen;

    vsnprintf(buf, MAXLINE, fmt, ap);

    snprintf(buf
+strlen(buf), MAXLINE-strlen(buf), ": %s\n", strerror(error));

    msglen  
= strlen( buf );

    fdopen( fileno, 
"ab" );

    fwrite( buf, msglen, 
1, fdopen( fileno, "ab" ) );

}

inline 
void dbg_err(const char * fmt, )

{

#ifdef DEBUG

    va_list        ap;

    va_start(ap, fmt);

    err_doit( fileno( stderr ), 
0, fmt, ap);

    va_end(ap);

#endif

}



int main()

{

    dbg_err( 
"my god!" );

    
return 0;

}




posted @ 2008-11-17 16:23  范晨鹏  阅读(1642)  评论(0编辑  收藏  举报