如何使特定的“无符号与零无意义的比较”警告沉默?

假设我有如下函数:

#define LOWER_BOUND 0 #define UPPER_BOUND 42 int is_value_in_range( some_typedef val) { return ((LOWER_BOUND <= val) && (val <= UPPER_BOUND)); } 

假设我已经正确配置了警告,如果some_typedef结果是无符号类型,我会得到一个警告,即无符号类型与0进行无意义的比较。当然这是真的,这是有道理的。

但是,让我说我确实希望对零的检查出于一个或多个可能的原因,例如:

  • 虽然边界始终是编译时常量,但它们可能会发生变化(并且宏可能不会“非常”接近函数)。 例如,可以通过将选项传递给编译器来设置边界。
  • 我可能希望防止以后将typedef更改为signed类型,因为typedef的每次使用都可能在更改时不会被仔细检查。

是否有一个体面,合理的便携方式来静音警告,而不是完全关闭它?

如果合理的话,依赖于’STATIC_ASSERT()’的function(可供我使用)是可以接受的。 如果类型更改以强制某人查看代码,我可以打破编译。 但值得注意的是, typeof并不是我在我所针对的所有编译器中都可用的。

我特意寻找C语言解决方案,因此模板在这里没有任何用处……

如果不知道some_typedef是未签名或签名的,我认为你几乎没有运气。

如果你事先知道some_typedef是无符号的,你可以使用

 #if LOWER_BOUND > 0 return ((LOWER_BOUND <= val) && (val <= UPPER_BOUND)); #else return ((val <= UPPER_BOUND)); #endif 

或者在这种情况下,您可以使用我的首选版本:

  return (val-LOWER_BOUND <= UPPER_BOUND-LOWER_BOUND); 

编辑:我将假设如果some_typedef不知道具有特定的签名,则UPPER_BOUNDLOWER_BOUND必须为正。 否则你会因some_typedef被提升为unsigned some_typedef得到非常古怪的结果。 因此,您可以随时安全地使用:

  return ((uintmax_t)val-LOWER_BOUND <= UPPER_BOUND-LOWER_BOUND); 

这通常由pragma控制。 对于MSVC,您有#pragma warning ,对于GCC,您有诊断编译指示 (当然不允许对MSVC的警告进行细粒度控制,但这就是您所拥有的)。

两者都允许推/弹机制只改变几行代码的警告。

我提出了一个非常简单直接的解决方案。 将下限复制到变量会导致编译器停止抱怨:

 #define LOWER_BOUND 0 #define UPPER_BOUND 42 int is_value_in_range( some_typedef val) { some_typedef lowerbound = LOWER_BOUND; return ((lowerbound <= val) && (val <= UPPER_BOUND)); } 

我希望在优化的构建中,编译器仍然能够轻松地摆脱不变的比较(尽管我必须validation)。

而不是试图使警告沉默,为什么不对它做些什么,并首先避免使用typedef? 您可以通过重载来处理特定情况,并避免屏蔽警告,更明确地声明您正在处理您正在处理的案例。 根据我的经验,这往往会迫使您测试新代码,而不是掩盖将来可能发生的事情(比如突然改变数据类型,然后不得不处理神秘地未达到预期范围的值)。