Почему сравнивается, если 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