2011-03-16 28 views
9

¿Qué pasa si no hago algo como esto:¿Qué sucede cuando resta un entero sin signo de un entero con signo en C++?

unsigned int u; 
int s; 

... 
s -= u; 

¿Cuál es el comportamiento esperado de esto:

1) Suponiendo que el entero sin signo no es demasiado grande para caber en el entero con signo?

2) ¿Asumiendo que el entero sin signo rebasaría el entero con signo?

Gracias.

+0

posible duplicado de [firmado a la conversión sin firmar en C - ¿siempre es seguro?] (Http://stackoverflow.com/questions/50605/signed-to-unsigned-conversion-in-c-is-it-always -seguro) –

+0

No es un duplicado completo. Esa pregunta tenía la última asignación en una variable 'unsigned', por lo que la aritmética es la misma pero la última asignación es diferente. –

+0

También vale la pena mirar: [* ¿Es el comportamiento definido de la resta entera sin signo? *] (Http://stackoverflow.com/q/7221409/1168156) :) – LihO

Respuesta

12

En general, consulte 5/9 en la norma.

En su ejemplo, la firmaron valor se convierte a unsigned (tomándolo UINT_MAX mod + 1), entonces la sustracción se realiza modulo UINT_MAX + 1 para dar un resultado sin signo.

Almacenar este resultado como un valor con signo a s implica una conversión integral estándar, esto es en 4.7/3. Si el valor está en el rango de signed int, se conserva; de lo contrario, el valor está definido por la implementación. Todas las implementaciones que he visto alguna vez han usado aritmética de módulo para insertarlo en el rango INT_MIN a INT_MAX, aunque como Krit dice, es posible que reciba una advertencia por hacer esto implícitamente.

Las implementaciones de "acrobacias" con las que probablemente nunca tratará podrían tener reglas diferentes para la conversión sin firmar-> firmada. Por ejemplo, si la implementación tiene una representación de signo-magnitud de enteros con signo, entonces no es posible convertir siempre tomando el módulo, ya que no hay forma de representar +/- (UNIT_MAX+1)/2 como int.

También es relevante 5,17/7, "El comportamiento de una expresión de la forma E1 op= E2 es equivalente a E1 = E1 op E2 excepto que E1 se evalúa sólo una vez". Esto significa que para decir que la resta se hace en el tipo unsigned int, todo lo que necesitamos saber es que s - u se hace en unsigned int: no existe una regla especial para -= que la aritmética se debe hacer en el tipo de LHS.

+0

Solo un recordatorio de que el "resultado definido por la implementación" podría ser ser una "señal definida de implementación". (El estándar C es mucho más claro al respecto en ) En la práctica, obtendrá los resultados correctos en la máquina de complemento de dos , resultados incorrectos en otros lugares. –

+0

@James: Creo que esa es una diferencia deliberada entre C++ y C, entonces. La redacción de C++ es bastante clara, "el valor está definido por la implementación".No dice, "el comportamiento está definido por la implementación", lo que permitiría una señal. –

-1

u se ha refundido como un entero con signo y se ha restado de s. En última instancia, el casting no hace ninguna diferencia. Un conjunto de bits se resta del otro y el resultado entra en s.

+1

Esta respuesta no está de acuerdo con la respuesta aceptada, que cita el estándar . – nobar

Cuestiones relacionadas