c++ - ¿Por qué comparar si un Int. Sin firma>=0 es una “Comparación sin sentido”?
for-loop comparison (9)
Me dieron una advertencia:
Pe186 "Comparación sin sentido de int sin signo con cero"
Cuando intenté compilar el siguiente código:
for(clLoop = cpLoopStart; clLoop >= 0; clLoop--)
{
//Do something
}
No entiendo porque Podría entender, si estuviera buscando un valor menor que cero, ya que un unsigned int
nunca puede ser negativo. Pero todo lo que busco aquí es si es igual a cero, lo que unsigned int
duda puede ser un unsigned int
sin unsigned int
.
Incluso podría ver este error si en este bucle intenté decrementar previamente en lugar de decrementar luego, pero nuevamente este no es el caso.
Comprueba si el int sin signo es mayor o igual que cero ( >=
). Esta expresión siempre será verdadera, porque los enteros sin signo nunca serán menores que cero.
El compilador intenta advertirle que está a punto de programar un bucle infinito.
Creo que querias decir
for(clLoop = cpLoopStart; clLoop; clLoop--)
{ //Do something
}
Debes eliminar =
en
clLoop >= 0
Digamos que su cpLoopStart is 5
.
Entonces, el valor de clLoop en la iteración adicional sería:
clLoop = 4;
clLoop = 3;
clLoop = 2;
clLoop = 1;
clLoop = 0;
clLoop = 0;
clLoop = 0;
clLoop = 0;
|
|
|
Infinite times.
Está comprobando si un int sin signo es igual o mayor que 0. Lo que siempre es cierto.
La advertencia se queja sobre su condición de interrupción de bucle for
clLoop >= 0
. El bucle terminará si clLoop
vuelve negativo, pero eso nunca sucederá para un int sin firmar.
Un entero sin signo nunca cae por debajo de 0, incluso después de disminuir infinitamente (es decir, clLoop >= 0
siempre será verdadero), lo que hace que la comparación no tenga sentido.
do {} while () puede ayudarlo a usar tipos de variables sin signo para bucle sin desbordamiento de enteros:
// 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;
}
Y compilarlo con:
gcc -std=c11 -Wall -Wextra -Wpedantic main.c
Salida:
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
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11) en Centos 7 x86_64 no da la advertencia.
Pero cuando el índice de bucle disminuye a -1
, el índice de bucle se convierte implícitamente a un valor que es igual a UINT_MAX ( limits.h )
UINT_MAX + 1u is equal to 0
. 0 - 1 is equal to UINX_MAX
.
limits.h Varias constantes dependientes de la plataforma propuestas por ANSI
Una de las soluciones alternativas es:
unsigned int clLoop, i;
for(i = cpLoopStart+1, clLoop = i-1; i > 0; i--, clLoop = i-1)
{
//Do something
}
Cambiaré en el rango [1, cpLoopStart + 1]
clLoop
cambiará en el rango [0, cpLoopStart]
clLoop >= 0
siempre es verdadero. No importa si realiza un decremento previo o posterior, un valor sin firmar es al menos 0. Cuando disminuye 0
obtiene UINT_MAX
.
El compilador calcula que es probable que no tenga la intención de hacer un bucle para siempre (o que habría usado una construcción diferente, que más obviamente hace un ciclo para siempre), de ahí la advertencia.