Cómo escribir un literal fundido en C
-
20-09-2019 - |
Pregunta
Tengo una función pequeña muestra:
#define VALUE 0
int test(unsigned char x) {
if (x>=VALUE)
return 0;
else
return 1;
}
Mi compilador me advierte que la comparación (x> = VALOR) es cierto en todos los casos, lo cual es correcto, porque x es un personaje sin signo y valor se define con el valor 0. Así que cambié mi código para:
if ( ((signed int) x ) >= ((signed int) VALUE ))
Sin embargo, la advertencia se produce de nuevo. Lo he comprobado con tres versiones del CCG (todas las versiones> 4,0, a veces hay que permitir que -Wextra).
En el caso cambiada, tengo esta conversión explícita y debe ser una comparación int firmado. ¿Por qué se afirma que la comparación es siempre verdad?
Solución
A pesar de la fundición, la comparación es cierto en todos los casos de comportamiento definido. El compilador todavía determina que (signed int)0
tiene el valor 0, y todavía determina que (signed int)x)
es no negativo si el programa ha definido comportamiento (casting de unsigned a firmado no está definido si el valor está fuera del intervalo para el tipo firmado).
Así que el compilador sigue advertencia, ya que continúa eliminando el caso más en conjunto.
Editar : Para silenciar la advertencia, escribir el código como
#define VALUE 0
int test(unsigned char x) {
#if VALUE==0
return 1;
#else
return x>=VALUE;
#endif
}
Otros consejos
x
es un unsigned char
, lo que significa que está entre 0 y 256. Puesto que un int
es más grande que un char
, fundición unsigned char
a signed int
todavía conserva las char
s valor original. Dado que este valor es siempre> = 0, su if
siempre es cierto.
Todos los valores de un abeto unsigned char
pueden perfectamente en su int
, por lo que incluso con el elenco nunca se tiene un valor negativo. El elenco que necesita es signed char
- sin embargo, en ese caso, debería declarar como x
signed
en la firma de la función. No hay ningún punto situado a los clientes que usted necesita un valor sin signo, cuando en realidad lo que necesita un ser firmado.
El #define
de VALUE
a 0
significa que su función se reduce a esto:
int test(unsigned char x) {
if (x>=0)
return 0;
else
return 1;
}
Desde x
siempre se pasa como un unsigned char
, entonces siempre tendrá un valor entre 0
y 255
incluido, independientemente de si lanzas x
o 0
a un signed int
en la declaración if
. El compilador, por tanto, le advierte de que x
será siempre mayor o igual que 0
, y que la cláusula else
nunca puede ser alcanzado.