Why Is Comparing if an Unsigned Int >= 0 a "Pointless Comparison"?
Asked Answered
A

10

23

I got warning:

Pe186 "Pointless comparison of unsigned int with zero"

when I tried to compile the following code:

for(clLoop = cpLoopStart; clLoop >= 0; clLoop--)                                  
{
    //Do something
}

I don't understand why. I could understand, if I were looking for a value less than zero, since an unsigned int can never be negative. But all I am looking for here is if it is equal to zero, which an unsigned int certainly can be.

I could even see this error if in this loop I tried to pre-decrement instead of post-decrement, but again that is not the case.

Actinic answered 21/2, 2011 at 13:12 Comment(3)
It makes no sense to think that such an error message could depend on pre or post (totally irrelevant here) incrementing or decrementing -- clLoop will take on every possible value either way. Also, if clLoop < 0 is a useless test (as it is), then clLoop >= 0 must also be a useless test, since (clLoop < 0) == !(clLoop >= 0).Jameyjami
possible duplicate of Why does "for (i = 100; i <= 0; --i)" loop forever?Extinguish
That's why while (clLoop--) { ... } is much better.Leclair
O
51

You check whether the unsigned int is greater than or equal (>=) zero. This expression will always be true, because unsigned integers will never be less than zero.

The compiler tries to warn you that you are about to program an infinite loop.

Opponent answered 21/2, 2011 at 13:14 Comment(0)
L
9

You are checking if an unsigned int is equal or greater than 0. Which is always true.

Loaf answered 21/2, 2011 at 13:14 Comment(0)
S
4

An unsigned integer never falls below 0 even after decrementing infinitely (i.e. clLoop >= 0 will always be true), which makes the comparison pointless.

Streptomycin answered 21/2, 2011 at 13:17 Comment(0)
B
3

I think you meant to say

for(clLoop = cpLoopStart; clLoop; clLoop--)                                  
{ //Do something
}
Blocked answered 21/2, 2011 at 14:54 Comment(0)
S
2

clLoop >= 0 is always true. It doesn't matter whether you pre-decrement or post-decrement, an unsigned value is at least 0. When you decrement 0 you get UINT_MAX.

The compiler figures that you probably don't mean to loop forever (or you'd have used a different construct, that more obviously loops forever), hence the warning.

Shope answered 21/2, 2011 at 13:14 Comment(0)
C
1

The warning complains about your for loop break condition clLoop >= 0. The loop will end if clLoop gets negative, but that will never happen for an unsigned int.

Cistaceous answered 21/2, 2011 at 13:15 Comment(0)
F
1

do{} while() can help you to use unsigned types of variable for loop without integer overflow:

// main.c
#include <stdio.h>

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;
}

And compile it with:

gcc -std=c11 -Wall -Wextra -Wpedantic main.c

Output:

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
Fixture answered 22/7, 2017 at 15:27 Comment(0)
D
0

gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11) in Centos 7 x86_64 does not give the warning.

But when loop index is decremented to -1, loop index is implicitly converted to a value which is equal to UINT_MAX (limits.h)

UINT_MAX + 1u is equal to 0. 0 - 1 is equal to UINX_MAX.

limits.h Various platform-dependent constants proposed by ANSI

One of alternative solution is:

unsigned int clLoop, i;

for(i = cpLoopStart+1, clLoop = i-1; i > 0; i--, clLoop = i-1)                                  
{
    //Do something
}

i will change in the range [1, cpLoopStart+1]

clLoop will change in the range [0, cpLoopStart]

Diaspore answered 21/5, 2017 at 15:53 Comment(0)
A
0

You should remove = in

clLoop >= 0

Let's say your cpLoopStart is 5.

Then, clLoop value in the further iteratiosn would be -

clLoop = 4;
clLoop = 3;
clLoop = 2;
clLoop = 1;
clLoop = 0;
clLoop = 0;
clLoop = 0;
clLoop = 0;
|
|
|
Infinite times.
Appoggiatura answered 29/11, 2018 at 21:53 Comment(0)
S
0

As already stated by others unsigned int is always >= 0 i.e. pointless comparison. Mayank Jindal posted for me the starting point for a solution.

To document the "fix" as a whole: do the following instead, this works as intended:

unsigned int cpLoopStart = 23U;
unsigned int clLoop = 0U;
for(clLoop = cpLoopStart; clLoop > 0U; clLoop--}
{
    //Do something
}

clLoop will start at 23 and end at 1 then exits the loop. I hope it was intended that clLoop will never be 0 inside the loop.

I also prefer to append "U" for unsigned typed values, this makes is clearer also when comparing values and variables.

Statuesque answered 17/6, 2020 at 9:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.