警告:布尔上下文中的“*”,建议使用“&&”代替 [-Wint-in-bool-context]?

warning: '*' in boolean context, suggest '&&' instead [-Wint-in-bool-context]?

我有这段代码(几乎都是“浮动的”):

#define sincf(x) (x == 0.0f) ? (1.0f) : (sinf(M_PI * x) / (M_PI * x))
// ...
for (int i = 0; i < num_taps; i++)
    proto[i] = 2.0f * f * sincf(2.0f * f * (i - m / 2.0f));
// ...

为什么 gcc 说 警告:'' 在布尔上下文中,建议将 '&&' 改为 [-Wint-in-bool-context]* 作为第二个“*”?

宏代入后,这部分

2.0f * f * sincf(2.0f * f * (i - m / 2.0f));

变成

 2.0f * f * (2.0f * f * (i - m / 2.0f) == 0.0f) ? ...

并且根据 operator precedence,乘法 2.0f * f * condition 将在检查条件是否为 true(有 ?)之前完成。像这样:

(2.0f * f * (2.0f * f * (i - m / 2.0f) == 0.0f)) ? ...

快速修复:

#define sincf(x) (((x) == 0.0f) ? (1.0f) : (sinf(M_PI * (x)) / (M_PI * (x))))

(x) == 0.0f 很少会是 true,但由于它仅用于避免被零除,所以可能没问题。

现在,这可以很容易地重写为 函数,我建议这样做。示例:

template<class T>
T sinc(T x) {
    if(x == T{}) return {1}; // avoid division by zero
    auto pix = static_cast<T>(M_PI) * x;
    return std::sin(pix) / pix;
}

如果 T 是整数类型,也可以将 x 转换为 double。这是它的 C++20 版本:

#include <concepts> // std::integral
#include <numbers>  // std::numbers::pi_v

template<class T>
T sinc(T x) {
    if(x == T{}) return 1; // avoid division by zero
    // C++20 added some constants to the standard library:
    auto pix = std::numbers::pi_v<T> * x;
    return std::sin(pix) / pix;
}

double sinc(std::integral auto x) {
    return sinc<double>(x);
}