2012-04-06 85 views
13

在大多数情况下,如果我想创建C中的可选功能,我只需创建两个函数是这样的:为什么GCC保留空功能?

#ifdef OPTIONAL_SOMETHING 
void do_something(int n, const char *s) 
{ 
    while (n--) { 
     printf("%s", s); 
    } 

    /* ...You might get the point, really do something... */ 
} 
#else 
void do_something(int n, const char *s) 
{ 
    /* Empty body */ 
} 
#endif 

因此,如果符号未定义 - 当功能被禁用 - 一个空函数被编译成可执行文件。

钻研组装上市,似乎GCC编译并呼吁空函数时的优化是禁用。如果启用优化,也与-O2-O3只编译必要的堆栈处理代码,但它优化了调用指令。总而言之,它保持了这个功能。

大约同样适用于非空的,但未使用的方法。

它应该简单地扔掉整个事情,但事实并非如此。为什么这是默认行为?只是为了好奇:我如何消除这种情况?

+0

“如果启用优化,同样使用-O2和-O3,它仅编译必要的堆栈处理代码,但它优化了调用指令。”这是否意味着这样还有一些开销? 'start_timer(); do_something(); stop_timer();'需要比'start_timer(); stop_timer();'更长的时间? – 2013-10-28 14:26:38

回答

24

由于函数具有外部链接(不是static),编译器无法消除它,因为另一个对象文件可能会引用它。如果功能是static,它将被完全消除。

+4

尽管如此,这仍然留下了为什么GCC没有内联函数体(即忽略调用)的问题。 – duskwuff 2012-04-06 22:33:44

+1

@duskwuff:我已经有编译器内嵌的静态函数,所以我不能在它们上设置断点,即使我想。它可能取决于GCC或平台的版本。否则,我不知道;我没有参与海湾合作委员会的发展,也没有参与有关这些问题的决定。 – 2012-04-06 22:35:27

+1

你让我好奇,所以我只是自己试了一下:我在gcc 4.4.5和-O3(只)我没有看到空函数被调用(无论是否静态)。 – timday 2012-04-06 23:22:35

1

如果您希望编译器最终内联您要告诉他的函数。声明你的函数inline,这允许编译器而不是发现函数,如果它看起来合适。

现在这可能会导致一个“未定义的符号”错误,当你编译-O0左右。把一个 “实例” 像

void do_something(int n, const char *s); 

在短短的一个编译单元(.c文件)。