如何告诉编译器#define 的“范围”(-Wtype-limits 警告)

pau*_*fer 4 c limit compiler-warnings

在我的代码中,我需要使uint32_t var范围内的变量饱和[MIN, MAX]MIN并被MAX定义为宏,因此我可以在头文件中轻松更改这些值。

标题:

#define MIN    (0)
#define MAX    (1000)
Run Code Online (Sandbox Code Playgroud)

代码:

if(var > MAX){
    var = MAX;
}else if(var < MIN){
    var = MIN;
}
Run Code Online (Sandbox Code Playgroud)

当我现在使用 compiler flag 时-Wtype-limits,我收到一条警告,即第二次检查var < MIN始终为 false。此警告表明我可以删除第二个比较。

只要我定义#define MIN (0),这就是有道理的,但是,当将其更改为 let's say 时#define MIN (10),则第二次比较是强制性的。

所以我的问题是:我怎么能告诉编译器,它MIN可以是大于或等于零的任何值?

phu*_*clv 5

最简单的解决方案是使用<=而不是<

if (var >= MAX) {
    var = MAX;
} else if (var <= MIN) {
    var = MIN;
}
Run Code Online (Sandbox Code Playgroud)

但是如果可能的话,你应该避免使用宏,而只声明常量。此外,U在处理无符号值时始终使用后缀,以避免出现有符号无符号不兼容警告。事实上,很有趣的是,如果我这样使用#define,我会在 GCC 而不是 Clang 中收到警告,当我更改为const并添加U后缀时,我不会收到GCC 的警告,但会收到Clang 的警告


sta*_*ark 3

这解决了这个问题:

int main(void) {
    unsigned int var = rand();

    if (var > MAX){
        var = MAX;
    }
#if MIN > 0
    else if (var < MIN) {
        var = MIN;
    }
#endif

    printf("token = %u\n", var);
}
Run Code Online (Sandbox Code Playgroud)

编辑:通过明确这两种情况来减少“肮脏”。

uint32_t saturate(uint32_t var)
{
#if MIN > 0
    if (var > MAX){
        var = MAX;
    }
    else if (var < MIN) {
        var = MIN;
    }
#else
    // Only need to do the upper bound
    if (var > MAX){
        var = MAX;
    }
#endif
    return var;
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一个相当肮脏的黑客行为,我希望看到很多评论来解释为什么它在那里。总体而言这不是一个好主意。 (3认同)