unsigned int(c++) vs uint(c#)
(3)
A continuación está el código c #:
static void Main(string[] args)
{
uint y = 12;
int x = -2;
if (x > y)
Console.WriteLine("x is greater");
else
Console.WriteLine("y is greater");
}
y este es el código de C ++:
int _tmain(int argc, _TCHAR* argv[])
{
unsigned int y = 12;
int x = -2;
if(x>y)
printf("x is greater");
else
printf("y is greater");
return 0;
}
Ambos están dando resultados diferentes. ¿Me estoy perdiendo algo básico? ¿Alguna idea?
C ++ y C # son idiomas diferentes. Tienen diferentes reglas para manejar la promoción de tipo en el caso de las comparaciones.
En C ++ y C, por lo general se comparan como si ambos no estuvieran firmados. Esto se llama "preservación sin firmar". Los compiladores C ++ y C usan tradicionalmente "preservación sin firmar" y el uso de esto se especifica en el estándar C ++ y en K & R.
En C #, ambos se convierten en largos firmados y luego se comparan. Esto se llama "preservar el valor". C # especifica la preservación del valor.
ANSI C también especifica la preservación del valor, pero solo cuando se trata de cortos y caracteres. Los pantalones cortos y los caracteres (firmados y sin firmar) se convierten de forma ascendente en enteros de una manera que preserva el valor y luego se comparan. Entonces, si un corto sin firmar se comparó con un corto firmado, el resultado saldría como el ejemplo de C #. Cada vez que se realiza una conversión a un tamaño mayor, se realiza de una manera que preserva el valor, pero si las dos variables tienen el mismo tamaño (y no pantalones cortos o caracteres) y ninguna está anotada, entonces se comparan como cantidades sin signo en ANSI C. Hay una buena discusión de los lados arriba y abajo de ambos enfoques en las preguntas frecuentes comp.lang.c.
En C ++, cuando compara un unsigned int
y un signed int
, el signed int
se convierte a unsigned int
. La conversión de un signed int
unsigned int
negativo a un unsigned int
se hace agregando UINT_MAX + 1
, que es mayor que 12
y, por lo tanto, el resultado.
En C #, si está obteniendo el resultado opuesto, significa que en C # ambas expresiones se están convirtiendo a signed int
signed long
( long
o System.Int64
) 1 y luego se comparan.
En C ++, su compilador debe haberle dado la advertencia:
advertencia: comparación entre expresiones enteras con signo y sin signo
Regla:
¡Siempre tome en serio las advertencias emitidas por el compilador!
1 Como lo señaló correctamente el editor en los comentarios.
No sé sobre el estándar de C #, pero en el estándar de C ++, usual arithmetic conversions
se aplicarían a ambos operandos de operadores relacionales:
[......enum, floating point type involed......] — Otherwise, the integral promotions (4.5) shall be performed on both operands. Then the following rules shall be applied to the promoted operands: — If both operands have the same type, no further conversion is needed. — Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank shall be converted to the type of the operand with greater rank. — Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type. — Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type. — Otherwise, both operands shall be converted to the unsigned integer type corresponding to the type of the operand with signed integer type.
Por lo tanto, cuando unsigned int
se compara con int
, int
se convertiría a unsigned int
, y -2
se convertiría en un número muy grande cuando se convirtiera a unsigned int
.