请考虑以下(有bug的)C++代码:
#include <cmath>
#include <cstdlib>
#include <iostream>
int main() {
if (abs(-0.75) != 0.75) {
std::cout << "Math is broken!\n";
return 1;
} else {
return 0;
}
}
这段代码有缺陷,因为它调用了abs
(意味着::abs
),而不是std::abs
。根据实现情况,::abs
可能不存在,也可能是C的abs
,或者它可能是一个包含double
版本的重载集合,就像std::abs
一样。在Linux使用Clang时,至少在我的环境中,结果为第二种情况:C的
abs
。这会引发两个警告,即使没有明确启用任何警告。<source>:7:9: warning: using integer absolute value function 'abs' when argument is of floating point type [-Wabsolute-value]
if (abs(-0.75) != 0.75) {
^
<source>:7:9: note: use function 'std::abs' instead
if (abs(-0.75) != 0.75) {
^~~
std::abs
<source>:7:13: warning: implicit conversion from 'double' to 'int' changes value from -0.75 to 0 [-Wliteral-conversion]
if (abs(-0.75) != 0.75) {
~~~ ^~~~~
在GCC上,我在不同的环境中得到了不同的结果,但我还没有弄清楚环境的哪些细节是相关的。更常见的选项是调用C语言的abs
函数。然而,即使使用-Wall -Wextra -pedantic
编译参数,它也不会给出任何警告。我可以通过-Wfloat-conversion
参数强制发出警告,但是这会导致我在代码库的其他部分获得太多的误报(也许我应该解决这个问题,但那又是另一个问题):
<source>: In function 'int main()':
<source>:7:18: warning: conversion to 'int' alters 'double' constant value [-Wfloat-conversion]
if (abs(-0.75) != 0.75) {
^
当我通过全局命名空间使用库函数时,是否有一种方法可以在命名空间std
中的版本是重载时发出警告?
std
名称空间。 - too honest for this siteextern "C"
所示)。 - too honest for this site