ProgramaciónDesarrollador C

¿Cuáles son las reglas de conversión de tipos (type conversion, type promotion) que se aplican en las expresiones en el lenguaje C? Proporcione ejemplos de errores inesperados y soluciones.

Supere entrevistas con el asistente de IA Hintsage

Respuesta

En el lenguaje C, en las expresiones a menudo ocurren conversiones de tipos (type promotion, type conversion), reguladas por el estándar:

  • Promoción de enteros: los tipos de menor tamaño (por ejemplo, char, short) son convertidos automáticamente a int o unsigned int antes de las operaciones aritméticas.
  • Conversiones aritméticas usuales: si los operandos son de diferentes tipos, se convierten al tipo "más amplio" según las reglas establecidas.
  • En operaciones mixtas de tipos firmados y no firmados, el resultado puede cambiar inesperadamente debido a la conversión.

Ejemplo:

unsigned short a = 65535; signed short b = -1; printf("%d ", a + b); // depende de la conversión!

Recomendación: preste atención a los tipos de los operandos, especialmente al trabajar con operaciones de bits, longitudes de arrays, índices, y evite mezclar implícitamente tipos firmados y no firmados.

Pregunta trampa

¿Qué imprimirá el siguiente fragmento?

unsigned int u = 1; int i = -2; printf("%d ", u + i);

Respuesta: La variable i se convertirá a unsigned int, el valor final será muy grande, ya que el resultado bajo el capó es: 1U + (unsigned int)-2U, lo que dará un número cercano a UINT_MAX (4294967295). Se imprimirá un número negativo solo si printf se formatea como int, de lo contrario, será un valor basura.

Ejemplos de errores reales debido a la falta de conocimiento sobre los matices del tema


Historia

En el cálculo de promedios de intensidad de imagen, se confundieron int y unsigned int. Los valores negativos se transmitieron incorrectamente a través de unsigned y produjeron números gigantes, provocando un desbordamiento del búfer de imagen.


Historia

En el firmware incorporado, calcularon la longitud de la cadena a través de size_t, pero indexaron el array a través de int. Al verificar la condición de salida de los límites del array, compararon int i >= size_t len, lo que rompió la lógica para cadenas largas y causó errores al comparar diferentes tipos (size_t es unsigned).


Historia

Un desarrollador en un proyecto financiero calculó el residuo de la división para números negativos usando %, olvidando que el signo del resultado para operandos negativos depende de la implementación. En un entorno, el resultado era positivo, en otro, negativo, lo que causaba que los cálculos "se desvíen" periódicamente.