Pregunta

Encontré esto en el código en el que estoy trabajando en este momento y pensé que era la causa de algunos problemas que estoy teniendo.

En un encabezado en alguna parte:

enum SpecificIndexes{
    //snip
    INVALID_INDEX = -1
};

Luego más tarde - inicialización:

nextIndex = INVALID_INDEX;

y usar

if(nextIndex != INVALID_INDEX)
{
    //do stuff
}

Depuración del código, los valores en nextIndex no tenían sentido (eran muy grandes), y descubrí que estaba declarado:

unsigned int nextIndex;

Entonces, la configuración inicial de INVALID_INDEX estaba desbordando el int sin firmar y configurándolo en un gran número. Supuse que eso era lo que estaba causando el problema, pero mirando más de cerca, la prueba

if(nextIndex != INVALID_INDEX)

Se estaba comportando correctamente, es decir, nunca ejecutó el cuerpo del if cuando nextIndex era el " large + ve value " ;.

¿Es esto correcto? ¿Cómo está pasando esto? ¿El valor de enumeración se convierte implícitamente en un int sin signo del mismo tipo que la variable y, por lo tanto, se ajusta de la misma manera?

¿Fue útil?

Solución

Sí a todo. Es un código válido, también se usa comúnmente en el código C ++ del lado de la biblioteca, más aún en C ++ moderno (es extraño cuando lo ves por primera vez, pero en realidad es un patrón muy común).

Luego, las enumeraciones son entradas firmadas, pero se convierten implícitamente en entradas no firmadas, ahora esto dependiendo de su compilador podría dar una advertencia, pero todavía se usa muy comúnmente, sin embargo, debe lanzar explícitamente para dejarlo claro a los mantenedores.

Otros consejos

Las enumeraciones

pueden estar representadas por tipos integrales con o sin signo de acuerdo con si contienen valores negativos y cómo se siente el compilador. El ejemplo aquí contiene un valor negativo y, por lo tanto, debe estar representado por un tipo integral con signo.

La comparación de igualdad entre tipos con signo y sin signo es segura y generalmente hace lo que el autor pretendía: el valor con signo se convertirá primero en sin signo, y el resultado de hacerlo está definido por el estándar C ++ y es intuitivo (al menos, es una vez que conoce el tipo de destino. Excepto si los enteros no son el complemento de dos. Entonces, tal vez no sea tan intuitivo, pero normalmente no causa problemas).

La comparación de pedidos es más probable que genere errores. Por ejemplo:

SpecificIndexes value = INVALID_VALUE;
return (value >= 0);

devuelve falso, pero:

unsigned int value = INVALID_VALUE;
return (value >= 0);

devuelve verdadero. A veces, el autor no apreciará la diferencia, especialmente si el tipo de "valor" no es tan obvio en el punto de uso. Sin embargo, el compilador puede advertir sobre el segundo ejemplo, porque (valor > = 0) es una tautología.

De hecho, -1 se convierte implícitamente en su valor equivalente sin signo cuando se asigna a nextValue. El equivalente sin signo es el valor con la misma representación en bits (que es 111111111111 ..., es decir, el valor máximo sin signo).

Más adelante, en la declaración de comparación, ocurre otro reparto implícito.

Entonces, esto funciona ahora, pero puede causar problemas en el futuro. Nunca es una buena idea mezclar valores con y sin signo.

Sí, creo que las enumeraciones están firmadas. Cambiar

unsigned int nextIndex;

a

int nextIndex;

y su programa debería funcionar.

El estándar C ++ permite que una implementación use un tipo firmado para enumeraciones pero no lo requiere. Por lo tanto, no puede suponer en general que es seguro colocar números negativos en una enumeración.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top