我正在使用 gcc 4.4.5 和-Wtype-limits
选项测试一个小代码段。
#include <assert.h>
#include <limits.h>
#include <stdint.h>
int main(void)
{
/* With other values of v, the behavior of the compiler is the same. */
uint16_t v = 0;
assert((unsigned int)INT_MAX < (unsigned int)v); /* l. 7 */
return 0;
}
然后,编译器抛出以下警告:
main.c:7: warning: comparison is always false due to limited range of data type
但是,据我所知,INT_MAX
可能等于+32767
(来自 C11(n1570),第5.2.4.2.1节整数类型的大小<limits.h>
)。在这种情况下,变量v
将能够保存值INT_MAX+1
,而assert
中的表达式将被评估为1
。
因此,我可以看到两个问题:
INT_MAX
不等于+32767
。在这种情况下,它会降低-Wtype-limits
对我的好处。它让我想到第二个选项是以下代码,它不会产生任何具有相同选项的警告。
#include <assert.h>
#include <limits.h>
#include <stdint.h>
int main(void)
{
assert((unsigned int)INT_MAX < (unsigned int)UINT16_MAX);
return 0;
}
那么,正确的答案是什么?
PS:顺便说一下,由于我的旧版 gcc ,我不得不道歉。也许下一个版本的行为是不同的。
答案 0 :(得分:4)
GCC确实考虑了类型的实际已知限制。它知道int
在你的情况下超过16位宽,所以它警告。
你没有得到
的警告#include <assert.h>
#include <limits.h>
#include <stdint.h>
int main(void)
{
assert((unsigned int)INT_MAX < (unsigned int)UINT16_MAX);
return 0;
}
因为标准在7.20.2(2)中说明:
任何已定义宏的每个实例都应替换为适用于
#if
预处理指令的常量表达式,并且此表达式应与作为相应对象的表达式具有相同的类型根据整数促销转换类型。
因此,对于32位宽int
s,宏UINT16_MAX
是int
,因此所涉及类型的限制并不能保证比较始终为假(或真)。