Почему сравнивается, если Unsigned Int >= 0 a "Беспредметное сравнение"?

Я получил предупреждение:

Pe186 "Бесцельное сравнение беззнакового int с нулем"

когда я попытался скомпилировать следующий код:

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

Я не понимаю, почему. Я мог понять, если бы искал значение меньше нуля, так как unsigned int никогда не может быть отрицательным. Но все, что я ищу здесь, это если оно равно нулю, что может быть unsigned int.

Я мог бы даже увидеть эту ошибку, если в этом цикле я попытался предсказать декремент вместо пост-декремента, но опять-таки это не так.

Ответы

Ответ 1

Вы проверяете, имеет ли unsigned int больше или равно (>=) ноль. Это выражение всегда будет истинным, поскольку целые числа без знака никогда не будут меньше нуля.

Компилятор пытается предупредить вас, что вы собираетесь запрограммировать бесконечный цикл.

Ответ 2

Вы проверяете, является ли unsigned int равным или больше 0. Это всегда верно.

Ответ 3

unsigned integer никогда не падает ниже 0 даже после бесконечного уменьшения (т.е. clLoop >= 0 всегда будет истинным), что делает сравнение бессмысленным.

Ответ 4

Я думаю, вы хотели сказать

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

Ответ 5

clLoop >= 0 всегда истинно. Не имеет значения, предваряете ли вы или уменьшаете пост-декремент, значение без знака равно по меньшей мере 0. Когда вы уменьшаете 0, вы получаете UINT_MAX.

Компилятор показывает, что вы, вероятно, не хотите, чтобы цикл навсегда (или вы бы использовали другую конструкцию, которая, очевидно, петли навсегда), поэтому предупреждение.

Ответ 6

Предупреждение жалуется на ваше условие прерывания цикла for clLoop >= 0. Цикл завершится, если clLoop получит отрицательный результат, но этого не произойдет для unsigned int.

Ответ 7

gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11) в Centos 7 x86_64 не дает предупреждения.

Но когда индекс цикла уменьшается до -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]

Ответ 8

do {} while() может помочь вам использовать неподписанные типы переменных для цикла без целочисленного переполнения:

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

И скомпилируйте его с помощью

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