HOWTO · C
Como comparar bits em C
Este artigo demonstra como comparar bits em C.
Nesta página
As operações bit a bit são fundamentais na programação de computadores, especialmente ao trabalhar com manipulação de dados de baixo nível. Em C, existem vários métodos para comparar bits individuais ou grupos de bits.
Neste artigo, exploraremos diferentes técnicas juntamente com exemplos de código para demonstrar cada método.
Implementar uma função personalizada usando operações XOR e AND bit a bit para comparação de bits em C
O operador AND bit a bit (&) é usado para realizar uma comparação bit a bit entre os bits correspondentes de dois operandos. Esta operação resulta em um novo valor em que cada bit é definido se e somente se os bits correspondentes em ambos os operandos estiverem definidos.
Código de exemplo:
#include <stdio.h>
int main() {
unsigned int num1 = 9; // Binary representation: 1001
unsigned int num2 = 6; // Binary representation: 0110
unsigned int result = num1 & num2;
printf("Result: %u\n", result); // Output: 0 (Binary: 0000)
return 0;
}
Saída:
Result: 0
Neste exemplo, num1 e num2 são inicializados com os valores 9 e 6, respectivamente. Esses valores são representados em binário como 1001 e 0110.
A operação AND bit a bit entre num1 e num2 (num1 & num2) resulta em 0000 em binário, que é 0 em decimal. Isso significa que nenhum bit correspondente está definido em ambos num1 e num2.
Enquanto isso, o operador XOR bit a bit (^) é usado para realizar uma comparação bit a bit entre os bits correspondentes de dois operandos. Esta operação resulta em um novo valor em que cada bit é definido se os bits correspondentes nos operandos forem diferentes.
Código de exemplo:
#include <stdio.h>
int main() {
unsigned int num1 = 9; // Binary representation: 1001
unsigned int num2 = 6; // Binary representation: 0110
unsigned int result = num1 ^ num2;
printf("Result: %u\n", result); // Output: 9 (Binary: 1001)
return 0;
}
Saída:
Result: 15
Neste exemplo, a operação XOR bit a bit (num1 ^ num2) resulta em 1001 em binário, que é 9 em decimal. Isso significa que os bits correspondentes em num1 e num2 são diferentes.
Geralmente, a comparação de bits envolve acessar valores de bit único e realizar as operações necessárias, como implementar um campo de bits usando as palavras-chave union e struct.
No entanto, as operações bit a bit oferecem um método mais eficiente de comparar bits especificados em números. Nesse caso, implementamos uma função separada adequada para o tipo u_int32_t, que tem a garantia de largura de 32 bits.
O programa de exemplo abaixo leva três inteiros como argumentos de linha de comando, os dois primeiros dos quais são os números que são comparados, enquanto o terceiro inteiro especifica o n-ésimo bit. Observe que convertemos elementos argv usando strtol, perdendo assim alguma precisão ao armazenar os valores de retorno no tipo u_int32_t.
A função compareBits declara duas variáveis locais que armazenam valores intermediários - mask e tmp. Definimos o n-ésimo bit na mask deslocando o 1 para a esquerda por nth - 1 posições.
Então, ambos os números de entrada do usuário são submetidos a XOR para obter as diferenças de bit em cada posição, com um bit definido no resultado denotando valores diferentes. Finalmente, precisamos extrair o bit da enésima posição e verificar se o valor é 0.
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
bool compareBits(u_int32_t n1, u_int32_t n2, u_int32_t nth) {
u_int32_t mask, tmp;
mask = 1 << (nth - 1);
tmp = n1 ^ n2;
if ((tmp & mask) == 0)
return true;
else
return false;
}
int main(int argc, char *argv[]) {
u_int32_t num1, num2, bit;
if (argc != 4) {
fprintf(stderr, "Usage: %s integer1 integer2 nth_bit \n", argv[0]);
exit(EXIT_FAILURE);
}
num1 = strtol(argv[1], NULL, 0);
num2 = strtol(argv[2], NULL, 0);
bit = strtol(argv[3], NULL, 0);
compareBits(num1, num2, bit) ? printf("bits equal!\n")
: printf("bits not equal!\n");
exit(EXIT_SUCCESS);
}
Formato do arquivo de exemplo:
./main 1234 1231 1
Formato do arquivo de entrada:
bits not equal!
Como exemplo, os inteiros 1234 e 1231 são representados em binário como 00000000000000000000010011010010 e 00000000000000000000010011001111, respectivamente.
Assim, aplicar XOR a esses dois resulta em uma representação binária 00000000000000000000000000011101, à qual finalmente se aplica AND com a máscara 00000000000000000000000000000010 para extrair o valor da posição de bit único. Se o resultado for todo zeros, isso implica que os bits comparados são iguais; caso contrário, é o oposto.
Alternativamente, porém, podemos encurtar a função compareBits e mover as operações XOR/AND para a instrução return, como mostrado no código de exemplo a seguir. Observe que a função retorna o oposto lógico das operações XOR/AND bit a bit, pois exibimos as mensagens correspondentes na função chamadora usando a instrução ternária ? :.
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
bool compareBits(u_int32_t n1, u_int32_t n2, u_int32_t nth) {
u_int32_t mask;
mask = 1 << (nth - 1);
return !((n1 ^ n2) & mask);
}
int main(int argc, char *argv[]) {
u_int32_t num1, num2, bit;
if (argc != 4) {
fprintf(stderr, "Usage: %s integer1 integer2 nth_bit \n", argv[0]);
exit(EXIT_FAILURE);
}
num1 = strtol(argv[1], NULL, 0);
num2 = strtol(argv[2], NULL, 0);
bit = strtol(argv[3], NULL, 0);
compareBits(num1, num2, bit) ? printf("bits equal!\n")
: printf("bits not equal!\n");
exit(EXIT_SUCCESS);
}
Formato do arquivo de exemplo:
./main 1234 1231 2
Formato do arquivo de entrada:
bits equal!
Usar o operador OR (|) bit a bit para comparação de bits em C
O operador OR bit a bit (|) realiza uma comparação bit a bit entre os bits correspondentes de dois operandos. O resultado desta operação é um novo valor em que cada bit é definido se pelo menos um dos bits correspondentes em qualquer um dos operandos estiver definido.
Quando aplicada a um par de bits, a operação OR segue esta lógica:
| `0 | 0` |
| `0 | 1` |
| `1 | 0` |
| `1 | 1` |
Considere o seguinte exemplo para ilustrar a operação OR bit a bit:
#include <stdio.h>
int main() {
unsigned int num1 = 9; // Binary representation: 1001
unsigned int num2 = 6; // Binary representation: 0110
unsigned int result = num1 | num2;
printf("Result: %u\n", result); // Output: 15 (Binary: 1111)
return 0;
}
Saída:
Result: 15
Neste exemplo, temos dois inteiros sem sinal, num1 e num2 inicializados com os valores 9 e 6, respectivamente. Suas representações binárias são 1001 e 0110.
Quando realizamos a operação OR bit a bit (num1 | num2), o resultado é 1111 em binário, que é 15 em decimal. Isso significa que pelo menos um dos bits correspondentes em num1 ou num2 está definido.
Usar o operador NOT (~) bit a bit para comparação de bits em C
O operador NOT bit a bit (~) é um operador unário, o que significa que opera em um único operando. Quando aplicado a um número binário, ele inverte cada bit, transformando 0s em 1s e 1s em 0s.
Código de exemplo:
#include <stdio.h>
int main() {
unsigned int num = 9; // Binary representation: 1001
unsigned int result = ~num;
printf(
"Result: %u\n",
result); // Output: 4294967286 (Binary: 11111111111111111111111111111010)
return 0;
}
Saída:
Result: 4294967286
Neste exemplo, declaramos uma variável inteira sem sinal num e a inicializamos com o valor 9. Em binário, isso é representado como 1001.
Em seguida, aplicamos o operador NOT bit a bit (~num). Isso inverte todos os bits, resultando em 11111111111111111111111111111010 em binário.
O resultado é impresso no console, que é 4294967286 em decimal.
NOT bit a bit para comparar bits
Uma das aplicações do operador NOT bit a bit é comparar bits. Ao inverter os bits de uma variável, podemos verificar facilmente se um bit específico está definido ou não.
Código de exemplo:
#include <stdio.h>
int main() {
unsigned int num = 9; // Binary representation: 1001
// Check if the 2nd bit is set
unsigned int mask = 1 << 1; // Shift 1 by 1 position to the left => 0002
unsigned int result = ~num & mask;
if (result == mask) {
printf("2nd bit is set.\n");
} else {
printf("2nd bit is not set.\n");
}
return 0;
}
Saída:
2nd bit is set.
Neste exemplo, queremos verificar se o 2º bit da variável num está definido.
Primeiro criamos uma máscara deslocando o 1 em 1 posição para a esquerda (1 << 1), resultando em 0002 em binário. Em seguida, aplicamos o operador NOT bit a bit a num, resultando em 11111111111111111111111111111010 em binário.
Em seguida, realizamos uma operação AND bit a bit entre o num invertido e a máscara. Isso isola o 2º bit.
Se o resultado for igual à máscara, significa que o 2º bit está definido e imprimimos uma mensagem correspondente. Caso contrário, imprimimos uma mensagem indicando que o 2º bit não está definido.
Conclusão
Nesta exploração abrangente dos operadores bit a bit em C, cobrimos operações fundamentais como AND, OR e NOT. Essas operações são inestimáveis para tarefas que envolvem manipulação de dados de baixo nível, como compactação de dados, criptografia e programação de sistemas embarcados.
Especificamente, aprofundamos o uso do operador NOT (~) bit a bit para comparar bits individuais. Ao aplicar o operador ~, podemos inverter facilmente os bits de uma variável, permitindo-nos verificar se um bit específico está definido ou não. Essa técnica é essencial em cenários em que é necessária uma manipulação precisa em nível de bit.
Compreender e dominar as operações bit a bit é crucial para programadores que trabalham em tarefas que envolvem interação direta com o hardware ou que exigem soluções otimizadas para ambientes com recursos limitados. Com o conhecimento adquirido neste artigo, você agora está equipado para aproveitar essas ferramentas poderosas em seus próprios projetos de programação em C.