我正在调试一个不返回任何内容的C函数(void)。最后我发现该函数没有副作用(它将指针作为参数并改变了指针本身)。
在我发现错误后,我感到困惑。为什么我的编译器没有给这个函数发出警告(即使我使用query = Price.query.filter(Price.product_id == data['product_id'])
query = query.filter(Price.min_qty >= data['quantity'])
price = query.filter(Price.max_qty <= data['quantity']).first()
和-Wall
)?显然这种功能毫无意义。
示例:
-Wextra
这是一个无用的功能,它实际上什么都不做。但是当我使用clang和gcc用void foo(int *a){
int b[2] = {1, 0};
a = b;
}
编译这个函数时,两者都没有显示警告并正常编译。
为什么呢?我知道当我使用-Wall -Wextra
时,这个函数将被优化为单个-O2
指令,没有任何副作用的未使用的变量和表达式将被给予警告(例如ret
而不使用int x;
之后,或x
)
我有clang 5.0和gcc 5.4.0
答案 0 :(得分:2)
我不是编译器编写者,所以不是根据个人经验说话,但我认为程序员偶然编写这种函数是非常罕见的。编译器警告适用于可能出错的事情。
在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
}
如果未包含任何可选功能,则该功能不执行任何操作。但这是完全合法的代码,作者不会在此处发出警告。
条件编译和更一般地使用预处理器是编译器如果发现一段代码被优化掉后不会发出警告的一个重要原因。如果任务可以在编译时完全执行,那太好了!执行期间花费的时间更少,没有失败的风险。警告通常不基于优化结果的另一个原因是警告很难理解,因为优化的代码与源代码的结构不同。大多数警告都是基于一个中间阶段,代码仍然广泛地看起来像源。
编译器做有时会警告无用的东西,但这是对程序员忘记某些事情的警告与编译时合法优化的事情的警告之间的妥协。
答案 1 :(得分:0)
编译器没有必要向您发出警告,因为代码不违反任何语法规则。
在C中,什么都不做的表达式(如1+1;
)基本上是一个未使用的表达式&#34;哪个符合规则,所以甚至不必强制发出警告!支持此类警告是可选的。这完全取决于编译器。
对于&#34;无用&#34;功能,它们比无用的更复杂&#34;表达式。所以也许编译器认为没有人会意外地编写无用的函数,所以它不会发出警告。