¿La conversión de no firmado a firmado está indefinida?

void fun(){ signed int a=-5; unsigned int b=-5; printf("the value of b is %u\n",b); if(a==b) printf("same\n"); else printf("diff"); } 

Se está imprimiendo:

4294967291

mismo

En la segunda línea, el valor firmado se convierte en un valor sin signo. Entonces b tiene el valor UINTMAX + 1 – 5 = 4294967291.

Mi pregunta es qué está sucediendo en la operación de comparación.

1) ¿Se vuelve a convertir a sin firmar y se compara con b?

2) ¿Se convertirá b (es decir, sin firma) a valor firmado y se comparará automáticamente?

3) ¿La conversión de no firmado a firmado está indefinida debido a un desbordamiento de int?

He leído otras publicaciones sobre el tema. Solo quiero una aclaración sobre las preguntas 2 y 3.

1) ¿Se vuelve a convertir a sin firmar y se compara con b?

Sí. En la expresión (a == b), se lleva a cabo la conversión de tipo implícita denominada “equilibrio” (el nombre formal es “las conversiones aritméticas habituales”). Las reglas de equilibrio especifican que si se comparan un operando firmado y sin firmar del mismo tamaño y tipo, el operando firmado se convierte en un sin signo.

2) ¿Se convertirá b (es decir, sin firma) a valor firmado y se comparará automáticamente?

No, nunca se convertirá en firmado en su ejemplo.

3) ¿La conversión de no firmado a firmado está indefinida debido a un desbordamiento de int?

Esto es lo que dice la norma: (C11)

6.3.1.3 Enteros firmados y sin firmar

1 Cuando un valor con tipo entero se convierte en otro tipo entero distinto de _Bool, si el valor puede representarse por el nuevo tipo, no se modifica.

2 De lo contrario, si el nuevo tipo no tiene firma, el valor se convierte sumndo o restando repetidamente uno más que el valor máximo que se puede representar en el nuevo tipo hasta que el valor esté en el rango del nuevo tipo.

3 De lo contrario, el nuevo tipo está firmado y el valor no puede representarse en él; o bien el resultado está definido por la implementación o se genera una señal definida por la implementación.

En otras palabras, si el comstackdor puede administrar hacer la conversión en 2) arriba, entonces el comportamiento está bien definido. Si no puede, entonces el resultado depende de la implementación del comstackdor.

No es un comportamiento indefinido.

Respuestas:

  1. a se convierte a unsigned int .
  2. Si a tuviera un rango más amplio que la contraparte firmada de b (me imagino que lo haría por long long a ), b se convertiría en un tipo firmado.
  3. Si un valor sin firmar no se puede representar correctamente después de la conversión a un tipo firmado, tendrá un comportamiento definido por la implementación. Si puede, no hay problema.
 b = -5; 

Eso cuenta como desbordamiento y es un comportamiento indefinido. La comparación de signed con unsigned promueve automáticamente los operandos a unsigned . -En caso de desbordamiento, se encontrará nuevamente en un caso de comportamiento indefinido.- simplemente mal, vea [editar] a continuación

Consulte también http://c-faq.com/expr/preservingrules.html .

[edit] Corrección – el estándar establece que los 2 complementos deben usarse al convertir de un signo negativo a un sin signo.