O operador til em C

95

Eu vi o operador til usado no algoritmo de hashing ELF e estou curioso para saber o que ele faz. (O código é de Eternally Confused .)

unsigned elf_hash ( void *key, int len )
{
  unsigned char *p = key;
  unsigned h = 0, g;
  int i;

  for ( i = 0; i < len; i++ ) {
    h = ( h << 4 ) + p[i];
    g = h & 0xf0000000L;

    if ( g != 0 )
      h ^= g >> 24;

    h &= ~g;
  }

  return h;
}
Paul Manta
fonte

Respostas:

126

O ~operador NÃO é bit a bit , ele inverte os bits em um número binário:

NOT 011100
  = 100011
GWW
fonte
1
O NOT bit a bit é útil para várias coisas, por exemplo, máscaras de bits. Não tenho certeza do que você quer dizer com conversão de inteiro não assinado em assinado.
GWW
2
Espere, você não deveria fazer o AND com a máscara de bits? é assim que meu leitor de bits está fazendo, mas é delicado. Eu li que se você tiver X e NÃO, subtrair um você obterá a versão não assinada de um número assinado, não é correto?
MarcusJ de
2
Eu uso NOT bit a bit em um bitmask em combinação com AND para limpar bits específicos antes de alterá-los.
GWW
2
Alguém perguntou sobre "conversão não assinada em assinada". A operação realizada por ~também é chamada de "complemento de um", que é uma forma de negação binária. Praticamente todos os computadores modernos usam a aritmética do complemento de dois, que é o inverso bit a bit mais um. Portanto, para uma variável de número inteiro com sinal x, você normalmente descobrirá que ~x + 1dá o mesmo valor que -x. Por exemplo, printf("%hx %hx\n", -1234, ~1234 + 1)imprime fb2e fb2ena minha máquina.
Steve Summit
2
@MarcusJ Sim, o complemento de um funciona para converter assinados em não assinados (assinado-> não assinados). (Observe que é mais fácil apenas atribuir o valor a uma variável declarada de forma diferente e deixar o compilador se preocupar com isso.) Mas não funciona ao contrário (sem sinal-> assinado), em parte porque os possíveis valores sem sinal abrangem uma faixa mais ampla do que pode ser amontoado em uma variável com sinal, e em parte porque esse problema não é bem definido sem especificar - provavelmente a partir de informações externas - que sinal inventar. Seus dois comentários receberam respostas diferentes porque especificam direções opostas.
Chuck Kollars
43

~é o operador NOT bit a bit. Ele inverte os bits do operando.

Por exemplo, se você tem:

char b = 0xF0;  /* Bits are 11110000 */
char c = ~b;    /* Bits are 00001111 */
dlev
fonte
12

Este é o operador NOT bit a bit. Ele vira todos os bits em um número: 100110 -> 011001

imortal
fonte
8

O caractere til é usado como um operador para inverter todos os bits de um inteiro (NOT bit a bit).

Por exemplo: ~0x0044 = 0xFFBB.

Cedekasme
fonte
7

É o operador NOT bit a bit. Ele inverte todos os bits em um valor inteiro.

Sander De Dycker
fonte
1

O operador Til (~), também chamado de operador NOT bit a bit, executa o complemento de qualquer número binário como argumento. Se o operando para NÃO for um número decimal, ele o converte em binário e realiza a operação de complemento de um.

Para calcular o complemento de um, basta inverter todos os dígitos [0 -> 1] e [1 -> 0] Ex: 0101 = 5; ~ (0101) = 1010. Uso do operador til: 1. É usado na operação de mascaramento, mascaramento significa definir e redefinir os valores dentro de qualquer registro. por ex:

char mask ;
mask = 1 << 5 ;

Ele definirá a máscara para um valor binário de 10000 e esta máscara pode ser usada para verificar o valor do bit presente dentro de outra variável.

int a = 4;
int k = a&mask ; if the 5th bit is 1 , then k=1 otherwise k=0. 

Isso é chamado de mascaramento de bits. 2. Encontrar o equivalente binário de qualquer número usando propriedades de mascaramento.

#include<stdio.h>
void equi_bits(unsigned char);
int main()
{
    unsigned char num = 10 ;
    printf("\nDecimal %d is same as binary ", num);
    equi_bits(num);
    return 0; 
} 
void equi_bits(unsigned char n)
{
  int i ; 
  unsigned char j , k ,mask ;
  for( i = 7 ; i >= 0 ; i--)
  {
     j=i;
     mask = 1 << j;
     k = n&mask ; // Masking
     k==0?printf("0"):printf("1");
  }  
}

Saída: Decimal 10 é igual a 00001010

Minha observação : para o intervalo máximo de qualquer tipo de dados, o complemento de um fornece o valor negativo diminuído em 1 para qualquer valor correspondente. ex:
~ 1 --------> -2
~ 2 ---------> -3
e assim por diante ... Vou mostrar esta observação usando um pequeno trecho de código

#include<stdio.h>
int main()
{
    int a , b;
    a=10;
    b=~a; // b-----> -11    
    printf("%d\n",a+~b+1);// equivalent to a-b
    return 0;
}
Output: 0

Nota: Isso é válido apenas para o intervalo de tipo de dados. significa que para o tipo de dados int, essa regra será aplicável apenas para o valor do intervalo [-2.147.483.648 a 2.147.483.647].
Obrigado ..... Que isso te ajude

Minion
fonte