¿Se puede usar memcpy para el tipo de juego de palabras?

Esta es una cita del estándar C11:

6.5 Expresiones
...

6 Eltipo efectivo de un objeto para acceder a su valor almacenado es el tipo declarado del objeto, si lo hay. Si un valor se almacena en un objeto que no tiene un tipo declarado a través de un valor que tiene un tipo que no es un tipo de carácter, entonces el tipo del valor se convierte en el tipo efectivo del objeto para ese acceso y para accesos posteriores que no modifican el valor almacenado. Si se copia un valor en un objeto que no tiene un tipo declarado usandomemcpy omemmove, o se copia como una matriz de tipo de caracteres, entonces el tipo efectivo del objeto modificado para ese acceso y para accesos posteriores que no modifican el valor es el tipo efectivo del objeto desde el cual se copia el valor, si tiene uno . Para todos los demás accesos a un objeto que no tiene un tipo declarado, el tipo efectivo del objeto es simplemente el tipo del valor l utilizado para el acceso.

7 Un objeto tendrá acceso a su valor almacenado solo mediante una expresión lvalue que tenga uno de los siguientes tipos:

- un tipo compatible con el tipo efectivo del objeto,
- una versión calificada de un tipo compatible con el tipo efectivo del objeto,
- un tipo que es el tipo con signo o sin signo correspondiente al tipo efectivo del objeto,
- un tipo que es el tipo con signo o sin signo correspondiente a una versión calificada del tipo efectivo del objeto,
- un tipo agregado o de unión que incluye uno de los tipos antes mencionados entre sus miembros (incluido, recursivamente, un miembro de una unión agregada o contenida), o
- un tipo de personaje.

¿Esto implica quememcpy no se puede usar para escribir de esta manera:

double d = 1234.5678;
uint64_t bits;
memcpy(&bits, &d, sizeof bits);
printf("the representation of %g is %08"PRIX64"\n", d, bits);

¿Por qué no daría el mismo resultado que:

union { double d; uint64_t i; } u;
u.d = 1234.5678;
printf("the representation of %g is %08"PRIX64"\n", d, u.i);

¿Qué pasa si uso mi versión dememcpy utilizando tipos de caracteres:

void *my_memcpy(void *dst, const void *src, size_t n) {
    unsigned char *d = dst;
    const unsigned char *s = src;
    for (size_t i = 0; i < n; i++) { d[i] = s[i]; }
    return dst;
}

EDITAR: EOF comentó queLa parte sobrememcpy() en el párrafo 6 no se aplica en esta situación, ya queuint64_t bits tiene un tipo declarado. Estoy de acuerdo, pero, desafortunadamente, esto no ayuda a responder la pregunta simemcpy puede usarse para el tipo de punteo, solo hace que el párrafo 6 sea irrelevante para evaluar la validez de los ejemplos anteriores.

Aquí hay otro intento de escribir conmemcpy que creo que estaría cubierto por el párrafo 6:

double d = 1234.5678;
void *p = malloc(sizeof(double));
if (p != NULL) {
    uint64_t *pbits = memcpy(p, &d, sizeof(double));
    uint64_t bits = *pbits;
    printf("the representation of %g is %08"PRIX64"\n", d, bits);
}

Asumiendosizeof(double) == sizeof(uint64_t), ¿El código anterior tiene un comportamiento definido en los párrafos 6 y 7?

EDITAR: Algunas respuestas apuntan al potencial de comportamiento indefinido proveniente de la lectura de una representación de trampa. Esto no es relevante ya que el Estándar C excluye explícitamente esta posibilidad:

7.20.1.1 Tipos enteros de ancho exacto

1 El nombre typedefintN_t designa un tipo entero con signo con anchoN, sin bits de relleno y una representación de complemento a dos. Así,int8_t denota un tipo entero con signo con un ancho de exactamente 8 bits.

2 El nombre typedefuintN_t designa un tipo entero sin signo con anchoN y sin partes de relleno. Así,uint24_t denota un tipo entero sin signo con un ancho de exactamente 24 bits.

Estos tipos son opcionales. Sin embargo, si una implementación proporciona tipos enteros con anchos de 8, 16, 32 o 64 bits, sin bits de relleno y (para los tipos con signo) que tienen una representación complementaria de dos, definirá los nombres de definición de tipo correspondientes.

Tipouint64_t tiene exactamente 64 bits de valor y no contiene bits de relleno, por lo que no puede haber ninguna representación de trampa.

Respuestas a la pregunta(5)

Su respuesta a la pregunta