c - 为什么 C 编译器在编写一个不返回任何内容且没有副作用的函数时不会给出警告?

标签 c compiler-warnings

我正在调试一个不返回任何内容 (void) 的 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 语言中,使用条件编译是相当常见的。根据编译时选项,某些代码被排除。像这样的函数并不罕见:

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
}

如果不包含任何可选功能,则该函数不执行任何操作。但这是完全合法的代码,作者不喜欢这里出现警告。

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

编译器有时会警告无用的东西,但这是对程序员忘记某些东西的警告和对编译时合法优化的东西发出警告之间的折衷。

关于c - 为什么 C 编译器在编写一个不返回任何内容且没有副作用的函数时不会给出警告?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46905462/

相关文章:

c++ - 对列表顶部的人最有可能说出的积极词汇和列表末尾的人很少说的积极词汇进行排序

visual-studio - 禁用警告 c4702 似乎不适用于 VS 2012

java - 缓解警告消息 "References to generic type Iterator<E> should be parameterized"?

c - Gstreamer RTSP 客户端超时问题

c - 在 C 中通过套接字发送结构

c - 在数组中绑定(bind)值并在 C 中动态返回数组

c - [ANSI-C]像类一样使用结构

C:数组错误初始化的奇怪行为

c++ - 使用枚举关闭 switch/case 语句的编译器警告

scala - 使用 -Ywarn-unused 时从 Scala 中的分析中排除类型证据参数