2011-12-19 8 views
5

Cuando intento compilar el siguiente programa C++ utilizando el compilador de Visual Studio 2010 C++ (X86) con nivel de advertencia/W4 habilitado, recibo una advertencia de falta de coincidencia línea marcadaC++: falta de coincidencia firmado/no firmado cuando solo se usan tipos sin firmar

#include <cstdio> 
#include <cstdint> 
#include <cstddef> 

int main(int argc, char **argv) 
{ 
    size_t idx = 42; 
    uint8_t bytesCount = 20; 

    // warning C4389: '==' : signed/unsigned mismatch 
    if (bytesCount + 1 == idx) 
    { 
     printf("Hello World\n"); 
    } 

    // no warning 
    if (bytesCount == idx) 
    { 
     printf("Hello World\n"); 
    } 
} 

Esto me confunde, ya que solo estoy usando tipos sin firmar. Dado que la comparación

bytesCount == idx 

hace que tal advertencia, es probable que tenga que ver con un poco de conversación implícita extraño que sucede aquí.

Por lo tanto, ¿cuál es el motivo por el que recibo esta advertencia y por qué reglas sucede esta conversación (si este es el motivo)?

Respuesta

5

1 es un int. El tipo de expresión aritmética integral depende de los tipos involucrados. En este caso, tiene un tipo unsigned y un tipo signed donde el tipo unsigned es más pequeño que el tipo signed. Esto entra en estándar el C++ en las expresiones (sección 5.10 [expr]):

De lo contrario, si el tipo del operando con el tipo entero con signo puede representar todos los valores del tipo del operando con unsigned tipo entero, el operando con tipo entero sin signo será convertido al tipo del operando con tipo entero con signo.

es decir, el tipo de la expresión bytesCount + 1 es int que está firmada por defecto.

9

1 es un literal firmado. Pruebe bytesCount + 1U.

El compilador es, probablemente, la creación de un valor temporal del tipo firmado debido a la adición de los valores con y sin signo (+ 1) bytesCount

3

Desde el 1 es de tipo int la expresión bytesCount + 1 es int (firmado).

De hecho, cuando se utiliza un tipo más pequeño que int en una expresión matemática que se asciende a int, por lo que incluso + bytesCount y bytesCount + bytesCount se consideran int y no uint8_t (mientras bytesCount + 1U es un unsigned int ya que es mayor de int) .

following program salidas true tres veces.

#include <iostream> 

int main() 
{ 
    unsigned short s = 1; 
    std::cout << (&typeid(s + 1U) == &typeid(1U)) << std::endl; 
    std::cout << (&typeid(+ s) == &typeid(1)) << std::endl; 
    std::cout << (&typeid(s + s) == &typeid(1)) << std::endl; 
} 
1

Las otras respuestas ya dicen que bytesCount + 1 se interpreta como signed int. Sin embargo, me gustaría agregar que en bytesCount == idx, bytesCount es también interpretado como signed int. Conceptualmente, primero se convierte a signed int, y solo se convierte a unsigned int después de eso. Su compilador no advierte sobre esto, porque tiene suficiente información para saber que realmente no hay problema. La conversión a signed int no puede hacer que bytesCount sea negativo.Comparar bytesCount + 1 es igualmente válido, igualmente seguro, pero es un poco más complejo para que el compilador ya no lo reconozca como seguro.

+0

Y cómo decirle al compilador que no me advierta sobre ese problema, si está claro desde el código del programa que la comparación es segura, pero no quiero deshabilitar las advertencias para todo el archivo, y no quiero hacer código feo para evitarlo ¿Existe alguna forma de lograr eso? – Arkady

+0

@Arkady Si el compilador está configurado para advertir sobre el código, no desea cambiar el código (porque será más feo), y no desea cambiar la configuración del compilador (porque suprimirá la información útil) advertencias también), no dejará muchas opciones abiertas. La única opción que puedo pensar que aún no descartó es piratear el compilador para mejorar su análisis. – hvd

Cuestiones relacionadas