为什么GCC保留空函数?

为什么GCC保留空函数?,c,function,optimization,gcc,macros,C,Function,Optimization,Gcc,Macros,在大多数情况下,如果我想在C中创建可选功能,我只需创建如下两个函数: #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, con

在大多数情况下,如果我想在C中创建可选功能,我只需创建如下两个函数:

#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
,则它只编译必要的堆栈处理代码,但优化了调用指令。总之,它保持了功能

同样的情况也适用于非空但未使用的方法


它应该干脆扔掉整个东西,但事实并非如此。为什么这是默认行为?出于好奇:我如何才能消除这种情况

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

如果你想让编译器最终内联函数,你必须告诉他。声明函数
内联
,这允许编译器在认为合适时不发出函数

现在,当您使用-O0编译时,这可能会导致“未定义符号”错误。放一个“实例化”如


仅在一个编译单元(.c文件)中。

这仍然存在一个问题,即当函数体为空时,为什么GCC不内联函数体(即省略调用)。@Dashwuff:编译器内联了静态函数,因此即使在我愿意的情况下,我也无法在它们上设置断点。但这可能取决于GCC的版本或平台。否则,我不知道;我没有参与GCC的开发,也不知道在这些问题上所做的决定。你让我好奇,所以我自己尝试了一下:我在GCC 4.4.5上,使用-O3(仅)我没有看到调用空函数(无论静态与否)。不,它们没有调用,它们只是存在而已。(Debian GCC 4.4.5-8)。编译器无法消除它们,因为不知道它们是否在翻译时使用。只有链接器才能消除它们,但只有当编译器被指示(通过一个特殊的
-f
选项,我忘记了它的名称)将每个函数放在自己的节中,并且链接器被告知垃圾收集未引用的节时,这才是可能的。“如果启用了优化,同时使用-O2和-O3,它只编译必要的堆栈处理代码,但它优化了调用指令。”这是否意味着这种方式仍然有一些开销?
start_timer();do_something();stop_timer();
start_timer();stop_timer();
花费的时间更长?
void do_something(int n, const char *s);