考虑以下示例:
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位,但在其他平台上并不能保证这一点。
答案 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人员提出更明智的行为,因为这些特殊类型的别名正在使用中。