>`) em C produz resultados inesperados ao mudar em 32 bits? " />
Comportamento inesperado do operador de deslocamento para a direita (1 >> 32)
No domínio da programação, o operador de deslocamento para a direita (>>) é comumente usado para realizar operações bit a bit, particularmente para dividir um número inteiro por uma potência de dois No entanto, um comportamento peculiar pode surgir ao mudar para valores maiores, conforme demonstrado pelo seguinte código C:
int foo(int a, int b) {
return a >> b;
}
int bar(uint64_t a, int b) {
return a >> b;
}
int main() {
std::cout > 32: " > 32) > (int)32: " > (int)32) Surpreendentemente, a saída deste programa revela resultados inesperados:
foo(1, 32): 1 // Should be 0
bar(1, 32): 0
1 >> 32: 0
(int)1 >> (int)32: 0
A lógica por trás desses resultados está no funcionamento interno da CPU e do compilador.
Comportamento da função foo()
Na função foo(), a operação de deslocamento é executada sem conversão, levando a CPU a realizar um deslocamento lógico para a direita. Em muitas arquiteturas, o deslocamento lógico para a direita é implementado como a >> (b % 32), ignorando efetivamente os bits superiores de b. Portanto, foo(1, 32) resulta em 1 >> (32% 32), que é avaliado como 1 >> 0, resultando em 1.
Por que a conversão para número inteiro de 64 bits é importante?
Na função bar(), um número inteiro sem sinal de 64 bits é fornecido, garantindo que o resultado seja garantido como 0 porque b (32) é menor que o número de bits no operando (64 ). No entanto, quando b é alterado para 64, o resultado se torna imprevisível e ainda pode render 1.
Otimização do compilador
No caso de 1 >> 32 e (int )1 >> (int)32, o compilador otimiza essas expressões constantes em tempo de compilação. O padrão especifica comportamento indefinido para deslocamentos à direita onde a contagem é negativa ou maior ou igual ao comprimento do operando. Como 32 excede o comprimento do operando, o compilador não pode determinar o resultado e gera 0 como um substituto seguro.
Comportamento específico da CPU
A implementação do deslocamento para a direita as operações podem variar entre diferentes CPUs. Em arquiteturas x86/x86-64, o deslocamento lógico para a direita é efetivamente a >> (b % 32 ou 64), dependendo do modo. Porém, em processadores ARM, a operação de deslocamento à direita garante zero para deslocamentos maiores ou iguais a 32.
Conclusão
Ao trabalhar com operadores de deslocamento à direita, é essencial para considerar possíveis comportamentos indefinidos, especialmente quando a contagem de deslocamentos excede o comprimento do operando. A conversão para tipos inteiros mais amplos, como inteiros de 64 bits, pode garantir resultados consistentes em diferentes CPUs e compiladores.
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3