Gostaria de saber por que o código abaixo imprime "errado".
double x = 0x8000000000000000;
signed long long v1 = (signed long long)(x);
signed long long v2 = *(signed long long *)(&x);
printf( v1 == v2? "correct\n" : "wrong\n" );
Tentei imprimir a representação binária de v1 e v2 respectivamente pelo código abaixo:
printf( "v1 = 0b" );
for ( int i = 63; i > 0; i-- ) {
printf( "%d", ( ( v1 >> i ) & 1 ) );
}
printf( "\n" );
printf( "v2 = 0b" );
for ( int i = 63; i > 0; i-- ) {
printf( "%d", ( ( v2 >> i ) & 1 ) );
}
printf( "\n" );
Acontece que v1 está correto, mas v2 é 0b010000111110000000000000000000000000000000000000000000000000000
.
Alguém poderia ser tão gentil em ensinar o que acontece aqui?
Também gostaria de saber se o padrão C oferece alguma maneira de imprimir a representação subjacente de binário ou hexadecimal, de modo que meu esquema de impressão possa ser substituído por uma chamada de função de uma linha?
No primeiro caso
o compilador realiza a conversão de
double
parasigned long long
.No segundo caso
o compilador interpreta a representação interna do double armazenado como um objeto do tipo
signed long long
.Preste atenção que os números float são armazenados internamente em formatos especiais.
Do Projeto Padrão C23 n3088:
Quanto à sua última pergunta, se não me engano, no Padrão C23 foi introduzido um especificador de conversão
b
que permite gerar números inteiros em uma representação binária.Quanto ao C++, a partir do Padrão C++20 você pode usar o especificador de formato
b
ouB
dentro da saída de formato (veja a descrição do cabeçalho<format>
)