【问题标题】:Function defined but not used warning in C在 C 中定义但未使用的函数警告
【发布时间】:2011-02-20 04:55:23
【问题描述】:

我有许多 C 源文件(.c 和 .h 文件)。头文件包含许多函数。在这些函数中,只有部分用于源 .C 文件。假设 a.h、b.h 是头文件,而 a.c 和 b.c 是 .c 文件。 a.h 包含在 a.c. 中。但是只有 a. 中的一些功能。 h 使用,其余不使用。编译后我发现以下警告:

 function XXXX defined but not used.

但是那些在 a.c 中没有使用的 XXXX 函数在 b.c 中使用了。所以,我也不能完全删除这些功能。所以,我决定制作一个单独的文件,只包含那些 XXXX 函数,并将它包含在任何使用它的地方。这样做会创建多个头文件。任何人都可以建议我一些有效的方法来解决这个问题。

【问题讨论】:

  • 这对我来说不是问题。您的函数声明或编译方式一定有些奇怪。能详细点吗?
  • 我认为我们需要查看一些代码,因为这通常不会发生 - 请参阅标准标题以获取示例
  • 没有愚蠢的警告。
  • 不重复该问题。我想说这个问题实际上并不是关于隐藏警告,而是关于消除这些警告背后的实际原因。

标签: c warnings


【解决方案1】:

“已定义但未使用的函数”警告仅针对具有内部链接的函数发出,即声明为static 的函数。这些函数只能在一个翻译单元中访问,因此编译器总是知道它们是否被使用(在程序中)。如果您没有在它们的翻译单元中引用这些函数,则这些函数被认为是未使用的,并且会生成警告。

您是说这些函数“不是在 a.c 中使用,而是在 b.c 中使用”。这不是真的。当您在头文件中将函数声明(并定义)为static 时,包含该头文件的每个翻译单元都会获得其自己的函数内部副本。尽管这些功能看起来完全一样,但它们仍然是独立的、完全独立的功能。它们具有相同的名称并包含相同的代码这一事实对编译器没有任何意义。因此,在b.c 中,您获得了该函数的完全独立副本,该功能已被使用(如您所说),但a.c 中的完全独立副本仍未使用。

在这种情况下的问题是为什么你这样做。你到底为什么要在头文件中定义 static 函数?如果您确实需要这样做(即,如果您真的想在每个翻译单元中生成此函数的单独内部“克隆”),您可以使用一些编译器特定的方法来解决警告。例如,在 GCC 中,您可以使用 __attribute__((unused)) 声明函数,并且不会再发出该函数的警告。

但通常不需要在头文件中定义函数。通常人们会使用带有 external 链接的函数(即没有 static),在其中一个 .c 文件中定义它,并将声明(原型)放在头文件中。在这种情况下编译器不会发出任何警告,即使函数已声明但未在某些翻译单元中使用。

【讨论】:

  • 当一个函数被翻译成另一个函数以赋予它更多意义时,这样做对于创建库很有用,例如static bool CanHazCheezBurger() { return flags & (HAZCHEEZ | HAZBURGER) }。它试图内联它,但它失败了,因为没有内联,只有复制。
  • 实际上,这可能是您无法删除的其他原因。在某些情况下,库中使用了一个通用宏,它定义了多个静态函数,但并非所有这些函数都会被使用。这是我们看到这种类型警告的部分原因,因此我们没有简单的解决方案而不进行大量更改以隐藏警告。不幸的是,attribute 似乎是推荐的解决方案,因为它不可移植。
  • 我听说在头文件中定义一个静态函数很有用,这样编译器就可以内联该函数(因为编译器内联外部函数更困难)。但是,随着编译器变得更好,我不确定这是否有必要了。
【解决方案2】:

如果您只想隐藏警告,请使用:

-Wno-unused-function

但是,您可能应该遵循caf's answer 中的建议。听起来您可能已经定义了一个函数,而您只是想添加它的声明。

【讨论】:

  • 根据我的阅读,我猜这些警告非常有效,不应该隐藏。我认为 Andrey 和 caf 是正确的,因为 OP 在 .h 文件中定义静态函数。简单地隐藏这些警告是没有帮助的;这很可能会导致更大的问题。
  • 你说得对,我认为上面caf的回答可能是正确的。 stackoverflow.com/questions/2845748/…我现在编辑了我的。
  • 我正在使用 cgo 制作包装器,并且知道这个标志很有用。
【解决方案3】:

另一种可能性是将这些函数定义为inline 而不是static。在这种情况下,它们需要在标题中定义,以便在调用它们的任何地方都可以看到定义。

编译器会在每个使用函数的地方内联代码,所以要小心这是你真正想要的。 Here's an answer 很好地讨论了这些权衡。

【讨论】:

  • 我以为 inline 关键字只是对编译器的建议?
  • @Michael 是和不是。关于实际内联函数,inline 只是一个建议。但是,在 C99 中,使用 inline 而没有 extern 定义的函数将永远从翻译模块中导出。换句话说,inline 强制执行static。但是,据我所知,它仍然会静音警告 - staticstatic inline 可以触发未使用的警告,单独的 inline 不会。
【解决方案4】:

作为“不要那样做”的替代方案,请考虑以下内容 - 一组将触发最多三个未使用函数警告的函数。

static int get_version_number(void) { return 42; }
static double hidden_global_variable(void) { return 3.14; }
static int potential_alternative_to_macro(int x) { return 4 * x; } 

再写一个函数,大概根据头文件的名字,

static void wno_unused_myheadername(void)
{
  /* don't need to actually call the functions to avoid the warnings */
  (void)&get_version_number;
  (void)&hidden_global_variable;
  (void)&potential_alternative_to_macro;
  return;
 }

我们现在只收到一个未使用的功能警告。如果在包含标头的文件中声明的任何外部函数中添加对 wno_unused_myheadername() 的调用,则整组未使用的函数警告将消失。因为它们现在都被使用了。

编译器将删除所有未使用的函数,包括 wno_unused_myheadername,因为它可以看到所有定义,并且可能确定对 wno_unused 函数的单个调用实际上没有做任何事情。

我已经检查了上面的内容是否按预期在 clang 和 gcc 下删除了警告,您的 milage 可能会因其他编译器而异。我没有查看 asm 输出来调查几乎未使用的函数何时被剥离。

至于为什么 - 一个很好的理由是使用许多非常适合在 C89 中内联的小函数,它们没有 inline 关键字,而不需要编译器的链接时间优化。

【讨论】:

    【解决方案5】:

    听起来您的问题是您在.h 文件中定义 函数。不要那样做。相反,只需将您的 声明 放在 .h 文件中,并拥有一个包含函数定义的匹配 .c 文件:

    common.h:

    #ifndef _COMMON_H
    #define _COMMON_H
    
    int foo(int a, int b);
    
    int bar(double x, double y, double z);
    
    #endif /* _COMMON_H */
    

    common.c:

    #include "common.h"
    
    int foo(int a, int b)
    {
        /* code */
    }
    
    int bar(double x, double y, double z)
    {
        /* code */
    }
    

    那么你的a.cb.c 应该是#include "common.h",你需要安排将common.c 编译成完整的程序。

    【讨论】:

      【解决方案6】:

      似乎没有人提到 .h 文件中的静态函数定义在 C 中制作了非常好的类型宏。我认为这是使用这种类型的构造的一种非常有效的方法,但是当然需要使其免于警告.

      caf 提出的 common.c/common.h 解决方案建议可以解决此类警告,而是为您可能不想要的函数的每个实例生成一个函数调用。

      【讨论】:

      • 请查看Help Center 了解如何写出好的答案。如果您想评论其他答案,请添加评论,而不是其他答案。
      猜你喜欢
      • 1970-01-01
      • 2014-08-29
      • 1970-01-01
      • 1970-01-01
      • 2020-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-14
      相关资源
      最近更新 更多