qué - ¿El tipo de juego de palabras a través de una unión no está especificado en C99 y se ha especificado en C11?
qué es un juego de palabras y 3 ejemplos (4)
Una serie de respuestas para la pregunta de desbordamiento de pila Obtener los bits de precisión simple de IEEE para un flotador sugiere usar una estructura de union
para el tipo de juego de palabras (por ejemplo: convertir los bits de un float
en un uint32_t
):
union {
float f;
uint32_t u;
} un;
un.f = your_float;
uint32_t target = un.u;
Sin embargo, el valor del miembro uint32_t
de la unión parece no estar especificado de acuerdo con el estándar C99 (al menos el borrador n1124), donde la sección 6.2.6.1.7 establece:
Cuando se almacena un valor en un miembro de un objeto de tipo unión, los bytes de la representación del objeto que no corresponden a ese miembro pero que corresponden a otros miembros toman valores no especificados.
Al menos una nota al pie de página del proyecto C11 n1570 parece implicar que ya no es el caso (véase la nota a pie de página 95 en 6.5.2.3):
Si el miembro utilizado para leer el contenido de un objeto de unión no es el mismo que el miembro utilizado por última vez para almacenar un valor en el objeto, la parte apropiada de la representación de objeto del valor se reinterpreta como una representación de objeto en el nuevo tipo como descrito en 6.2.6 (un proceso a veces llamado '''' tipo de juego de palabras ''''). Esto podría ser una representación de trampa.
Sin embargo, el texto de la sección 6.2.6.1.7 es el mismo en el borrador C99 que en el borrador C11.
¿Este comportamiento realmente no está especificado en C99? ¿Se ha especificado en C11? Me doy cuenta de que la mayoría de los compiladores parecen soportar esto, pero sería bueno saber si está especificado en el estándar, o simplemente en una extensión muy común.
Sin embargo, esto parece violar el estándar C99 (al menos el borrador n1124), donde la sección 6.2.6.1.7 establece algunas cosas. ¿Este comportamiento realmente no está especificado en C99?
No, estás bien.
Cuando se almacena un valor en un miembro de un objeto de tipo unión, los bytes de la representación del objeto que no corresponden a ese miembro pero que corresponden a otros miembros toman valores no especificados.
Esto se aplica a bloques de datos de diferentes tamaños. Es decir, si tiene:
union u
{
float f;
double d;
};
y le asigna algo a f, cambiaría los 4 bytes inferiores de d, pero los 4 bytes superiores estarían en un estado indeterminado.
Las uniones existen principalmente para el tipo de juego de palabras.
El comportamiento del tipo de juego de palabras con unión cambió de C89 a C99. El comportamiento en C99 es el mismo que C11.
Como Wug anotó en su respuesta, se permiten los juegos de palabras tipo C99 / C11. Se lee un valor no especificado que podría ser una trampa cuando los miembros de la unión son de diferente tamaño.
La nota a pie de página se agregó en C99 después del Informe de defectos de plumas Clive DW # 257 :
Finalmente, uno de los cambios de C90 a C99 fue eliminar cualquier restricción para acceder a un miembro de una unión cuando la última tienda era una diferente. El razonamiento era que el comportamiento dependería de las representaciones de los valores. Dado que este punto a menudo se malinterpreta, bien podría valer la pena aclararlo en el Estándar.
[...]
Para abordar el problema del "tipo de juego de palabras", adjunte una nueva nota al pie 78a a las palabras "miembro con nombre" en 6.5.2.3 # 3: 78a Si el miembro utilizado para acceder al contenido de un objeto de unión no es el mismo que el miembro usado para almacenar un valor en el objeto, la parte apropiada de la representación del objeto del valor se reinterpreta como una representación del objeto en el nuevo tipo como se describe en 6.2.6 (un proceso que a veces se llama "tipo de juego de palabras"). Esto podría ser una representación de trampa.
La redacción de Clive DW Feather fue aceptada para un Corrigendum técnico en la respuesta del Comité C para el Informe de defectos # 283 .
Esto siempre ha sido "dudoso". Como otros han notado, se agregó una nota a pie de página a C99 a través de un Corregmentum técnico. Se lee de la siguiente manera:
Si el miembro utilizado para acceder al contenido de un objeto de unión no es el mismo que el miembro utilizado por última vez para almacenar un valor en el objeto, la parte apropiada de la representación de objeto del valor se reinterpreta como una representación de objeto en el nuevo tipo como descrito en 6.2.6 (un proceso a veces llamado "tipo de juego de palabras"). Esto podría ser una representación de trampa.
Sin embargo, las notas a pie de página se especifican en el Prólogo como no normativas:
Los anexos D y F forman una parte normativa de este estándar; los anexos A, B, C, E, G, H, I, J, la bibliografía y el índice son meramente informativos. De acuerdo con la Parte 3 de las Directivas ISO / IEC, este prólogo, la introducción, notas, notas al pie y ejemplos también son solo informativos .
Es decir, las notas a pie de página no pueden proscribir el comportamiento; solo deberían aclarar el texto existente. Es una opinión impopular, pero la nota a pie de página citada anteriormente en realidad falla en este sentido, no existe tal comportamiento proscrito en el texto normativo. De hecho, hay partes como 6.7.2.1:
... El valor de como máximo uno de los miembros se puede almacenar en un objeto de unión en cualquier momento
En conjunción con 6.5.2.3 (con respecto al acceso a los miembros del sindicato con el operador "."):
El valor es el del miembro nombrado
Es decir, si se puede almacenar el valor de un solo miembro, el valor de otro miembro no existe. Esto implica fuertemente que el tipo de juego de palabras a través de una unión no debería ser posible; el acceso de miembro produce un valor inexistente. El mismo texto todavía existe en el documento C11.
Sin embargo, está claro que el propósito de agregar la nota al pie fue para permitir el juego de palabras; es solo que el comité aparentemente rompió las reglas en las notas al pie que no contienen texto normativo. Para aceptar la nota al pie, realmente tiene que ignorar la sección que dice que las notas a pie de página no son normativas, o tratar de descubrir cómo interpretar el texto normativo de tal manera que respalde la conclusión de la nota al pie (que he intentado, y fallado, hacer).
La sección que citas:
Cuando se almacena un valor en un miembro de un objeto de tipo unión, los bytes de la representación del objeto que no corresponden a ese miembro pero que corresponden a otros miembros toman valores no especificados.
... tiene que ser leído cuidadosamente, sin embargo. "Los bytes de la representación del objeto que no corresponden a ese miembro " se refieren a bytes más allá del tamaño del miembro, lo cual no es un problema para el tipo de juego de palabras (excepto que no puede asumir que escribir a un miembro del sindicato dejará parte "extra" de cualquier miembro más grande sin tocar).
La especificación C99 original dejó esto sin especificar.
Una de las corrigenda técnicas de C99 (TR2, creo) agregó la nota al pie 82 para corregir este descuido:
Si el miembro utilizado para acceder al contenido de un objeto de unión no es el mismo que el miembro utilizado por última vez para almacenar un valor en el objeto, la parte apropiada de la representación de objeto del valor se reinterpreta como una representación de objeto en el nuevo tipo como descrito en 6.2.6 (un proceso a veces llamado "tipo de juego de palabras"). Esto podría ser una representación de trampa.
Esa nota al pie se conserva en el estándar C11 (es la nota al pie 95 en C11).