为什么比较一个无符号的Int> = 0一个“无意义的比较”?
我收到警告:
Pe186“无符号int与零的无意义比较”
当我尝试编译以下代码时:
for(clLoop = cpLoopStart; clLoop >= 0; clLoop--) { //Do something }
我不明白为什么。 我能理解,如果我正在寻找一个小于零的值,因为unsigned int
永远不会是负数。 但我在这里寻找的是它是否等于零, unsigned int
当然可以。
我甚至可以看到这个错误,如果在这个循环中我试图预先减少而不是后减量,但是情况并非如此。
检查unsigned int是否大于或等于( >=
)零。 此表达式始终为true,因为无符号整数永远不会小于零。
编译器试图警告您即将编程无限循环。
您正在检查unsigned int是否等于或大于 0.这总是正确的。
无限递减后,无符号整数永远不会低于0(即clLoop >= 0
将始终为真),这使得比较毫无意义。
我想你想说
for(clLoop = cpLoopStart; clLoop; clLoop--) { //Do something }
clLoop >= 0
始终为true。 无论是预先递减还是后递减都无关紧要,无符号值至少为0.当您递减0
您将得到UINT_MAX
。
编译器认为您可能并不意味着永远循环(或者您使用了不同的构造,更明显地循环),因此警告。
警告抱怨你的for
循环中断条件clLoop >= 0
。 如果clLoop
负数,循环将结束,但对于unsigned int,这将永远不会发生。
do {} while()可以帮助您在没有整数溢出的情况下使用无符号类型的变量for循环:
// main.c #include int main(void) { int array[] = {1,2,3,4,5,6,7,8,9,10}; unsigned int size = sizeof(array)/sizeof(int); // size == 10; unsigned int i = size; do { i--; printf("Index: %u, content: %d\n",i,array[i]); } while(i > 0); return 0; }
并编译它:
gcc -std=c11 -Wall -Wextra -Wpedantic main.c
输出:
Index: 9, content: 10 Index: 8, content: 9 Index: 7, content: 8 Index: 6, content: 7 Index: 5, content: 6 Index: 4, content: 5 Index: 3, content: 4 Index: 2, content: 3 Index: 1, content: 2 Index: 0, content: 1
Centos 7 x86_64中的gcc(GCC)4.8.5 20150623(Red Hat 4.8.5-11)没有给出警告。
但是当循环索引递减到-1
,循环索引会隐式转换为等于UINT_MAX( limits.h )的值
UINT_MAX + 1u is equal to 0
。 0 - 1 is equal to UINX_MAX
。
limits.h ANSI提出的各种与平台相关的常量
替代解决方案之一是:
unsigned int clLoop, i; for(i = cpLoopStart+1, clLoop = i-1; i > 0; i--, clLoop = i-1) { //Do something }
i
会改变范围[1,cpLoopStart + 1]
clLoop
将在[0,cpLoopStart]范围内变化