representação de armadilha

  1. O que é representação de trap em C (alguns exemplos podem ajudar)? Isso se aplica ao C ++?

    float f=3.5; int *pi = (int*)&f; 
  2. Edit: Eu sei que ‘pi’ viola a regra de aliasing e é UB de acordo com o padrão C. Pelo menos no GCC não produz erros, mas avisos. Nesta implementação (ou seja, GCC), assumindo sizeof(int) == sizeof(float) do f e *pi tem a mesma representação / padrão binário? E quanto ao MSVC?

  1. Uma representação de trap é um termo genérico usado pelo C99 (IIRC não por C89) para descrever padrões de bits que se encheckboxm no espaço ocupado por um tipo, mas desencadeiam comportamento indefinido se usados ​​como um valor desse tipo. A definição está na seção 6.2.6.1p5 (com tentáculos em todo o 6.2.6) e não vou citá-lo aqui porque é longo e confuso. Um tipo para o qual tais padrões de bits existem é dito ter “representações de armadilhas”. Nenhum tipo é requerido para ter representações de armadilhas, mas o único tipo que o padrão garante que não terá representações de armadilhas é unsigned char (6.2.6.1p5, 6.2.6.2p1).

    O padrão dá dois exemplos hipotéticos de representações de armadilhas, nenhuma das quais corresponde a qualquer coisa que qualquer CPU real tenha feito por muitos anos, então eu não vou confundir você com elas. Um bom exemplo de uma representação de interceptação (também a única coisa que se qualifica como uma representação de interceptação de nível de hardware em qualquer CPU que você possa encontrar) é uma sinalização NaN em um tipo de ponto flutuante. C99 O Anexo F (seção 2.1) explicitamente deixa indefinido o comportamento de NaNs de sinalização, mesmo que o IEC 60559 especifique seu comportamento em detalhes.

    Vale a pena mencionar que, embora os tipos de ponteiro possam ter representações de interceptação, os pointers nulos não são representações de interceptação. Ponteiros nulos só causam um comportamento indefinido se forem desreferenciados ou desviados; outras operações neles (mais importante, comparações e cópias) são bem definidas. As representações de interceptação causam um comportamento indefinido se você simplesmente as ler usando o tipo que possui a representação de interceptação. (Se marcadores inválidos, mas não nulos, são ou deveriam ser considerados representações de armadilhas é um assunto de debate. A CPU não os trata dessa maneira, mas o compilador pode.)

  2. O código que você mostra tem comportamento indefinido, mas isso é devido às regras de alias de ponteiro, não por causa das representações de interceptação. Isto é como converter um float no int com a mesma representação (assumindo, como você diz, sizeof(float) == sizeof(int) )

     int extract_int(float f) { union { int i; float f; } u; uf = f; return ui; } 

    Este código tem comportamento não especificado (não indefinido) em C99, o que basicamente significa que o padrão não define qual valor inteiro é produzido, mas você obtém algum valor inteiro válido, não é uma representação de trap e o compilador não tem permissão para otimizar no pressuposto de que você não tenha feito isso. (Seção 6.2.6.1, parágrafo 7. Minha cópia do C99 pode include a crítica técnica – minha lembrança é que esta foi indefinida na publicação original, mas foi alterada para não especificada em um TC.)

Comportamento indefinido para alias a float com um ponteiro para int.

Em geral, qualquer valor de ponto flutuante não interceptado IEEE-754 pode ser representado como um número inteiro em algumas plataformas sem nenhum problema. No entanto, existem valores de ponto flutuante que podem resultar em comportamento inesperado se você assumir que todos os valores de ponto flutuante têm uma representação de inteiro exclusiva e forçar o FPU a carregar esse valor.

(Exemplo retirado de http://www.dmh2000.com/cpp/dswap.shtml )

Por exemplo, ao trabalhar com dados FP, você precisa empacotar entre CPUs com endianness diferente, você pode pensar em fazer o seguinte:

double swap(double)

Infelizmente, se o compilador carrega a input em um registrador de FPU e é uma representação de trap, a FPU pode escrevê-la de volta com uma representação de armadilha equivalente que por acaso é uma representação de bit diferente.

Em outras palavras, existem alguns valores FP que não possuem uma representação de bit correspondente se você não converter corretamente (por correto eu quero dizer através de uma union , memcpy via char * ou outro mecanismo padrão).