为什么 C 编译器在编写 returns 什么都没有且没有副作用的函数时不会给出警告?

Why won’t C compiler give a warning when writing a function which returns nothing and has no side effect?

我正在调试一个 returns 什么都没有(无效)的 C 函数。最后我发现这个函数没有副作用(它以一个指针作为参数并改变了指针本身)。

发现错误后,我一头雾水。为什么我的编译器没有对此函数发出警告(即使我使用 -Wall-Wextra)?显然这种功能是没有意义的。

示例:

void foo(int *a){
    int b[2] = {1, 0};
    a = b;
}

这是一个无用的函数,实际上什么也不做。但是当我用clang和gcc用-Wall -Wextra编译这个函数时,都没有显示警告并且编译正常。

为什么?我知道当我使用 -O2 时,这个函数将被优化为单个 ret 指令,并且没有任何副作用的未使用变量和表达式将给出警告(例如 int x; 和不使用x 以后,或 1 + 1;)

我有 clang 5.0 和 gcc 5.4.0

编译器没有必要向您发出警告,因为代码没有违反任何语法规则。

在 C 语言中,什么都不做的表达式(如 1+1;)基本上是一个 "unused expression",它完全符合规则,因此甚至不必为此发出警告!对此类警告的支持是可选的。这一切都取决于编译器。

对于"useless"函数,它们比"useless"表达式更复杂。所以可能编译器认为没有人不小心写了无用函数,所以没有给出警告

我不是编译器编写者,所以不是个人经验,但我认为程序员不小心写出这种功能的情况很少见。编译器警告是针对可能出错的事情。

在 C 中,使用条件编译是相当普遍的。根据编译时选项,一些代码被排除在外。像这样的功能并不少见:

void cleanup(void) {
#ifdef INCLUDE_FROBNICATOR
     frob_close();
#endif
#ifdef INCLUDE_WIDGET_HANDLER
     for (size_t i = 0; i < WIDGET_COUNT; i++)
         destroy_widget(widgets[i]);
     }
#endif
}

如果包含 none 个可选功能,则该函数不执行任何操作。但这是完全合法的代码,作者不希望在这里收到警告。

条件编译和更普遍地使用预处理器是编译器在注意到一段代码被优化掉时不发出警告的一个重要原因。如果一个任务可以完全在编译时执行,那就太好了!执行过程中花费的时间更少,没有失败的风险。警告通常不基于优化结果的另一个原因是警告可能非常难以理解,因为优化后的代码与源代码的结构不同。大多数警告都基于一个中间阶段,在这个阶段代码仍然大致看起来像源代码。

编译器 do 有时会警告无用的东西,但这是在警告程序员忘记某些东西的情况和警告编译时合理优化的东西之间的折衷。