O memcpy pode ser usado para punção de tipo?

Esta é uma citação do padrão C11:

6.5 Expressões
...

6 Otipo eficaz de um objeto para um acesso ao seu valor armazenado é o tipo declarado do objeto, se houver. Se um valor for armazenado em um objeto sem tipo declarado por meio de um lvalue com um tipo que não seja um tipo de caractere, o tipo do lvalue se tornará o tipo efetivo do objeto para esse acesso e para acessos subseqüentes que não modificam o valor armazenado. Se um valor for copiado em um objeto sem tipo declarado usandomemcpy oumemmove, ou é copiado como uma matriz do tipo de caractere, o tipo efetivo do objeto modificado para esse acesso e para acessos subseqüentes que não modificam o valor é o tipo efetivo do objeto do qual o valor é copiado, se houver um. . Para todos os outros acessos a um objeto sem tipo declarado, o tipo efetivo do objeto é simplesmente o tipo de lvalue usado para o acesso.

7 Um objeto deve ter seu valor armazenado acessado apenas por uma expressão lvalue que possui um dos seguintes tipos:

- um tipo compatível com o tipo efetivo do objeto,
- uma versão qualificada de um tipo compatível com o tipo efetivo do objeto,
- um tipo que é o tipo assinado ou não assinado correspondente ao tipo efetivo do objeto,
- um tipo que é o tipo assinado ou não assinado, correspondente a uma versão qualificada do tipo efetivo do objeto,
- um tipo agregado ou de união que inclua um dos tipos mencionados acima entre seus membros (incluindo, recursivamente, um membro de uma união subagregada ou contida), ou
- um tipo de personagem.

Isso implica quememcpy não pode ser usado para punção de tipo desta maneira:

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

Por que não daria a mesma saída que:

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

E se eu usar minha versão domemcpy usando 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: A EOF comentou queA parte sobrememcpy() no n.º 6 não se aplica nesta situação, uma vez queuint64_t bits tem um tipo declarado. Concordo, mas, infelizmente, isso não ajuda a responder à pergunta sememcpy pode ser usado para punção de tipo, apenas torna o parágrafo 6 irrelevante para avaliar a validade dos exemplos acima.

Aqui está outra tentativa de digitar commemcpy que eu acredito que seria coberto pelo parágrafo 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);
}

Assumindosizeof(double) == sizeof(uint64_t), O código acima tem um comportamento definido nos parágrafos 6 e 7?

EDITAR: Algumas respostas apontam para o potencial de comportamento indefinido decorrente da leitura de uma representação de armadilha. Isso não é relevante, pois o padrão C exclui explicitamente essa possibilidade:

7.20.1.1 Tipos inteiros de largura exata

1 O nome do typedefintN_t designa um tipo inteiro assinado com larguraN, sem bits de preenchimento e uma representação do complemento de dois. Portanto,int8_t denota um tipo inteiro assinado com uma largura de exatamente 8 bits.

2 O nome do typedefuintN_t designa um tipo inteiro não assinado com larguraN e sem pedaços de preenchimento. Portanto,uint24_t denota um tipo inteiro não assinado com uma largura de exatamente 24 bits.

Esses tipos são opcionais. No entanto, se uma implementação fornecer tipos inteiros com larguras de 8, 16, 32 ou 64 bits, sem bits de preenchimento e (para os tipos assinados) que possuírem uma representação de complemento de dois, deverá definir os nomes de typedef correspondentes.

Tipouint64_t possui exatamente 64 bits de valor e nenhum bit de preenchimento, portanto, não pode haver representações de trap.

questionAnswers(5)

yourAnswerToTheQuestion