Advertencia del compilador (nivel 2) C4146

operador unario menos aplicado a un tipo sin signo; el resultado aún no tiene signo

Los tipos sin signo solo pueden contener valores no negativos, por lo que no suele tener sentido usar el operador unario menos (negación) cuando se aplica a un tipo sin signo. Tanto el operando como el resultado no son negativos.

Comentarios

Cuando se expresa un literal entero negativo, el - delante del valor se analiza como un operador unario de negación. El compilador aplica el operador después de analizar el valor numérico. Si el valor numérico se ajusta al intervalo de un tipo entero sin signo, pero no al tipo entero con signo correspondiente, el compilador interpreta el valor como sin signo. El operador unario de negación no cambia un valor sin signo.

Esta advertencia suele producirse cuando se intenta expresar el valor int mínimo, -2147483648, o el valor long long mínimo, -9223372036854775808. Estos valores no se pueden escribir como -2147483648 o -9223372036854775808ll, respectivamente. El motivo es que el compilador procesa la expresión en dos fases: en primer lugar, analiza el valor numérico y, luego, aplica el operador de negación. Por ejemplo, cuando el compilador analiza -2147483648, sigue estos pasos:

  1. Se evalúa el número 2147483648. Dado que es mayor que el valor int máximo de 2147483647, pero todavía cabe en un unsigned int, el tipo de 2147483648 es unsigned int.

  2. El operador unario menos se aplica al valor sin signo, con un resultado sin signo, el que también resulta ser 2147483648.

El tipo sin signo del resultado puede provocar un comportamiento inesperado. Si el resultado se usa en una comparación, se puede usar una comparación sin signo; por ejemplo, cuando el otro operando es int.

Para evitar la advertencia C4146, use INT_MIN o LLONG_MIN desde <limits.h> o el equivalente de C++, <climits>. Estos valores tienen tipos con signo.

La opción del compilador /sdl (Habilitar comprobaciones de seguridad adicionales) eleva esta advertencia a un error.

Ejemplo

En el ejemplo siguiente se muestra el comportamiento inesperado que puede producirse cuando el compilador genera la advertencia C4146:

// C4146.cpp
// compile with: /W2
#include <iostream>

void check(int i)
{
    if (i > -9223372036854775808ll)   // C4146
        std::cout << i << " is greater than the most negative long long int.\n";
}

int main()
{
    check(-100);
    check(1);
}

En este ejemplo, el compilador considera -9223372036854775808ll como sin signo, aunque el literal tenga un sufijo ll y se aplique el operador de negación. Para hacer la comparación <, el compilador promueve silenciosamente i con signo a unsigned long long int. La segunda línea esperada, 1 is greater than the most negative long long int, no se imprime porque ((unsigned long long int)1) > 9223372036854775808ull es false.

Para corregir el ejemplo, incluya <climits> y cambie -9223372036854775808ll a LLONG_MIN.

Consulte también

Operador unario de negación (-)