¿Qué se supone que significa el casting?

18

Cuando codifique en lenguajes de bajo nivel como CI, descubra que la conversión a veces significa 'reinterpretar estos bytes como si siempre hubiera sido de este otro tipo' y otras veces como 'convertir este valor de manera inteligente en este otro tipo'.

¿Cuál es el significado original de la palabra y hay alguna coherencia en cuándo esperar una conversión y cuándo esperar una reinterpretación en bruto?

Alexander Torstling
fuente
¿Qué hay en el artículo de Wikipedia que no entiendes? " Conversión de tipo , encasillamiento y la coacción son diferentes maneras de, implícita o explícitamente, el cambio de una entidad de un tipo de datos en otro ... Cada lenguaje de programación tiene sus propias reglas sobre cómo se pueden convertir tipos ..."
mosquito
El significado original de "lanzar" no tiene nada que ver con la programación, ver aquí merriam-webster.com/dictionary/cast
Doc Brown
1
Muchos (principalmente desde una perspectiva de lenguaje administrado) en el blog de Eric Lippert en la categoría de operador de reparto
AakashM
1
@gnat: No estoy seguro si esa es una pregunta seria o solo un intento de trolling. Pero me gustaría saber cómo saber qué hará el compilador: ¿convertir, lanzar o coaccionar? ¿Cuáles son las reglas generales?
Alexander Torstling
1
@DocBrown Creo que el término casten el sentido de la informática es más similar a la fundición en el sentido de la metalurgia, por el cual la forma de un metal fundido se reforma cuando se vierte en un molde: britannica.com/EBchecked/topic/377665/metallurgy/81884/Casting
KChaloux

Respuestas:

10

Lanzar en C es único, muy diferente a otros lenguajes. Tampoco es nunca inteligente.

La conversión en C convierte los valores de un tipo a otro utilizando reglas cuidadosamente definidas. Si realmente necesita saber, lea el estándar. De lo contrario, los puntos principales son:

  1. La conversión entre tipos enteros preserva el valor, si es posible. Si el destino tiene más bits, esto se está ampliando y generalmente es seguro, pero puede implicar la extensión del signo. Si es más angosto, se perderán los bits.
  2. La conversión entre tipos de puntero conserva el valor del puntero, pero los resultados a menudo son indefinidos, a menudo no portátiles y a menudo útiles para escenarios avanzados.
  3. La conversión entre tipos enteros y punteros está bien si el entero es lo suficientemente grande y conserva el patrón de bits (lo que sea que eso signifique). Si el número entero es demasiado pequeño, el resultado no está definido pero no es útil. Como regla, 'largo' es lo suficientemente ancho como para 'nulo *', ¡pero no hay garantías! Los punteros creados de esta manera pueden ser inválidos, en todo tipo de formas interesantes.
  4. La conversión entre los tipos flotante y entero son conversiones aritméticas definidas por una rutina de biblioteca apropiada (con truncamiento, no redondeo).
  5. Puede emitir el valor de retorno de una función para anular. Yo nunca he. No hace nada

Algunos lanzamientos se aplican implícitamente, y en algunos de ellos el compilador emitirá una advertencia. ¡Lo mejor es prestar atención a las advertencias!

La definición del diccionario para el reparto se ignora mejor, ya que no es útil. Muchos lanzamientos se describen mejor con los términos conversión o coerción, por lo que vale la pena conocerlos también.

C ++ es MUCHO más complicado, pero no lo preguntaste, ¿verdad?

david.pfx
fuente
Estoy interesado en las reglas generales, y no en detalles minúsculos, pero estoy interesado en otros lenguajes que C si eso ayuda a aclarar las cosas.
Alexander Torstling
2
Lo que he dado aquí es tan genérico como razonable. Para escribir código C / C ++ profesional real de bajo nivel, el detalle minúsculo es crítico. La mayoría de los idiomas simplemente no tienen este tipo de problema en sus conversiones de tipos. Lo siento si no resuelve tu problema.
david.pfx
Excepto que la conversión de T*a void*y de regreso es siempre bien definido.
Miles Rout
@Miles: En realidad, se requiere convertir T * a cualquier U * y viceversa para preservar el valor del puntero original. En mi respuesta, solo dije 'a menudo indefinido' para mantenerlo breve, 'porque algunos de los detalles son muy confusos.
david.pfx
1
@supercat: Ver n1570 S6.3.2.3. La conversión / ida y vuelta entre T *, U * y void * siempre conserva el valor del puntero con solo una excepción. Si alguna T * no está alineada correctamente, es un comportamiento indefinido. Acepto tu punto, pero solo hasta ese punto.
david.pfx
2

Esta parte del diccionario Webster da la definición adecuada:

a: para dar forma a (una sustancia) vertiendo líquido o plástico en un molde y dejando que se endurezca sin presión
b: formando mediante este proceso

Entonces, antes de lanzar, su "objeto" (no literalmente un objeto OOP) está en una forma (tipo) dada. Cuando lo vuelves a lanzar, eso es "vierte hormigón" a su alrededor para darle una nueva forma, eso es lo que haces con la fundición. Tienes un número como un entero en forma de hexágono, y después de lanzar, obtendrás una cadena en forma de rectángulo.

Juha Untinen
fuente
2
Además : "Para asignar un determinado rol a (un actor)".
Kelly Thomas
Sip. Estoy seguro de que este es el mejor. +1.
david.pfx
2

Puede ser útil separar los moldes de C en dos grupos:

  1. Conversiones numéricas: convierta un número entre una representación en otra, intentando mantener el valor. Por ejemplo, (int)3.1sería 3. Hay reglas exactas que definen lo que sucede cuando no se puede mantener el valor exacto.

  2. Lanzamientos de puntero: mantenga la dirección de memoria, pero cambie la forma en que se desreferencia. Por ejemplo, for float x=3.5, *(int *)&xdará 1080033280- este número entero está representado por el mismo patrón de bits que representa el flotante 3.5.

Ugoren
fuente
Keep the memory address, but change the way it's dereferenced.No se define la referencia a un puntero de tipo punteado. El estándar sólo garantiza la fundición de A *a B *y la parte posterior producirá la misma A *, que puede no haber sido válido para eliminar la referencia en el 1er lugar - o que si B *es una char *, puede ser utilizado para leer la representación de objetos de cualquier tipo. Para todos los demás tipos, el B *puntero de desreferenciación es punteo de tipo, UB y viola el alias estricto. De todos modos, incluso si el compilador no descartó el ejemplo 2 anterior por esa razón, está haciendo suposiciones inportables sobre patrones de bits
underscore_d
1
cast (v): to receive form in a mold

En C ++, los diversos tipos de conversiones pueden hacerse más explícitos, con el reinterpret_castsignificado de "tratar estos bytes como si ya fueran esta otra cosa". En C puede hacerlo absolutamente explícito utilizando a union, la conversión con el (type)operador intentará mantener el resultado numéricamente equivalente, hasta la pérdida de precisión.

U2EF1
fuente
2
En C, los moldes de puntero siempre se reinterpretan y los moldes de valor siempre conservan el valor de la mejor manera posible. En C ++ hay varias formas de realizar una conversión de puntero, razón por la cual existen los tipos de conversión más explícitos.
Jan Hudec
La semántica de puntero en C no es necesariamente "reinterpretada". Sería legítimo para un procesador que utilizara el direccionamiento de palabras pero quisiera interactuar muy bien con el código basado en bytes para tener una int*palabra y char*dos palabras [con el segundo byte seleccionando el byte alto o bajo de una palabra]. Lanzar un (int*)to (char*)requeriría la adición de una palabra adicional que debería ser cualquier valor que especifique el primer byte del int.
supercat