2010-12-03 12 views
8

¿Por qué GCC advierte solo para las situaciones 1 y 3 y no 2 en el siguiente código?GCC no advierte cuando se usa == op con una var firmada y un literal sin firmar

Estoy compilando con banderas de -Wall y -g.

int main() { 

    unsigned int ui = 4; 
    int si = 6; 

    if (si == ui) { // Warning comparison b/w signed and unsigned 
     printf("xxxx"); 
    } 

    if (si == 2U) { // No Warning --- WHY ??? 
     printf("xxxx"); 
    } 

    if (si > 2U) { // Warning comparison b/w signed and unsigned 
     printf("xxxx"); 
    } 

    return 0; 
} 

Respuesta

4

http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html:

-Wconversion sección:

No avisar de conversiones explícitas como abs ((int) x) y ui = (unsigned) -1, o si el valor no se cambia por la conversión al igual que en abs (2.0).

Desde 2U es literal, gcc saber que:

  • si si < 0, entonces (unsigned) si >= 2^31, por lo tanto, s1 != 2U.
  • si si > 0, entonces (unsigned) si tiene el mismo valor que si, por lo tanto (unsigned) si == 2U si y solo si si == 2.

En conclusión, la comparación de la si firmado con literal 2U es la misma que la comparación de si con 2, es decir, el resultado de si == 2U sería no ser cambiado mediante la conversión de si a unsigned.

Si se compara con 2^32-1 (4294967295U), el más grande de entero sin signo de 32 bits, que no es representable en int, entonces si podría ser igual a él, incluso si si sí es negativo, esto no puede sea ​​lo que usted quería, entonces se genera una advertencia con la opción -Wextra.

1

Posiblemente porque no hay ambigüedad en una comparación de igualdad con constante en el rango donde las versiones firmadas y no firmadas del tipo se superponen.

Si lo cambio a

if (si == 2147483648U) { printf("xxxx"); }

recibo una advertencia

(En realidad, he tenido que añadir -Wextra antes de llegar a las advertencias que informamos)

0

gracias por Chris tu respuesta. Creo que lleva a la causa. Mi idea original era que el sufijo U causaría que este literal fuera promovido a un tipo sin signo, pero creo que solo se promociona a un tipo sin firmar cuando el número es mayor que INT_MAX_32 que es> 2147483647.

+0

Es de hecho ' promocionado 'a unsigned, pero no hay diferencia cuando su valor es menor que 2^31 - 1. –

+0

@ryanli: si siempre se promociona a unsigned, entonces si == 2U también debería lanzar una advertencia. ¿Por qué es 2147483647 el punto mágico donde, con solo la bandera de la pared, debería comenzar a lanzar una advertencia? Supongo que no entiendo tu respuesta inicial. – nisah

+0

porque '2U' es un literal, y aunque' si' está 'signed', gcc sabe claramente en tiempo de compilación que' si' se puede comparar con el valor de '2U' sin perder precisión: si' si' es negativo en sí mismo , no es igual a '2U' después de promocionado a unsigned. Pero para valores literales mayores que 2^31-1, gcc lanza una advertencia ya que 'si' podría ser igual al literal si' si' es negativo, lo que puede no ser el resultado esperado. Y '-Wall' no advierte nada, como lo muestra el enlace en mi respuesta. –

Cuestiones relacionadas