【问题标题】:Why does GCC keep empty functions?为什么 GCC 保留空函数?
【发布时间】:2012-04-20 10:55:11
【问题描述】:

在大多数情况下,如果我想在 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,它只编译必要的堆栈处理代码,但会优化调用指令。总而言之,它保留了功能。

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

它应该简单地扔掉整个东西,但事实并非如此。为什么这是默认行为?只是为了好奇:我怎样才能消除这个?

【问题讨论】:

  • "如果启用了优化,同样使用 -O2 和 -O3 它只会编译必要的堆栈处理代码,但会优化调用指令。"这是否意味着这种方式仍有一些开销? start_timer();do_something();stop_timer(); 花费的时间比 start_timer();stop_timer(); 长?

标签: c function optimization gcc macros


【解决方案1】:

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

【讨论】:

  • 这仍然留下了一个问题,即为什么当已知函数体为空时 GCC 不内联函数体(即省略调用)。
  • @duskwuff:我有编译器内联的静态函数,因此我无法在它们上设置断点,即使我愿意。它可能取决于 GCC 的版本或平台。否则,我不知道;我没有参与 GCC 的开发,也不知道就这些问题做出的决定。
  • 你让我很好奇,所以我自己尝试了这个:我在 gcc 4.4.5 和 -O3 (仅限)我看不到空函数被调用(无论是否静态)。
  • 不,他们不叫他们只是存在。 (Debian GCC 4.4.5-8)。
  • 编译器无法消除它们,因为不知道它们是否在翻译时使用。只有链接器才能消除它们,但这只有在编译器被指示(通过一个我忘记名字的特殊 -f 选项)将每个函数放在它自己的部分中,并且如果链接器被告知垃圾 -收集未引用的部分。
【解决方案2】:

如果您希望编译器最终内联您必须告诉他的函数。声明你的函数inline,这允许编译器not在它认为合适的时候发出函数。

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

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

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

【讨论】:

    猜你喜欢
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    • 2014-03-16
    • 2015-12-20
    • 1970-01-01
    • 2021-07-02
    • 1970-01-01
    • 2013-01-04
    相关资源
    最近更新 更多