-Wtype-limits尝试限制无符号整数

时间:2017-05-13 16:13:49

标签: c++ c gcc

考虑以下示例:

unsigned short c = // ...
if (c > 0xfffful)
    c = 0xfffful;

由于unsigned short实际上可能大于16位,因此我想将以{十六进制格式snprintf之前的值限制为固定大小的缓冲区。

但是,GCC(但不是clang)会发出警告:comparison is always false due to limited range of data type [-Wtype-limits]

这是GCC中的错误还是我错过了什么?我知道在我的机器上unsigned short正好是16位,但在其他平台上并不能保证这一点。

2 个答案:

答案 0 :(得分:2)

我说它不是一个bug。海湾合作委员会声称if (c > 0xfffful)永远是假的,在你的机器上是真的。海湾合作委员会很聪明,能够抓住这个,而铿锵不是。 干得好GCC!

另一方面,GCC并不聪明,没有注意到虽然你的机器总是假的,但别人的机器上并不总是假的。 加油GCC!

请注意,在C ++ 11中,*_least##_t类型appear(我保留被证明是错误的权利!)由typedef实现。当GCC运行它的警告检查时,它可能不知道原始数据类型是uint_least16_t。如果是这种情况,编译器将无法推断在其他系统上比较可能是真的。更改GCC以记住原始数据类型可能非常困难。我不是在捍卫海湾合作委员会的天真警告,而是在暗示为什么可能难以解决。

我很想知道海湾合作委员会的人对此有何看法。你有没有考虑过filing an issue

答案 1 :(得分:0)

这似乎不是一个错误(可能它可能被认为是一个稍微天真的功能),但我可以看到为什么你想要这个代码以便于移植。< / p>

如果没有任何标准宏来告诉你平台上的类型大小(并且没有任何内容),我可能会在构建过程中迈出一步,然后通过以-D定义将其作为您的程序。

e.g。在Make:

if ...
   CFLAGS += -DTRUNCATE_UINT16_LEAST_T
endif

然后:

#ifdef TRUNCATE_UINT16_LEAST_T
    if (c > 0xfffful)
        c = 0xfffful;
#endif

Makefile条件基于configure中的步骤的输出,或执行其他只打印出sizeof的C ++程序。可悲的是,这排除了交叉编译。

从长期来看,我建议向GCC人员提出更明智的行为,因为这些特殊类型的别名正在使用中。