El operador de tilde en C

95

He visto el operador de tilde utilizado en el algoritmo de hash ELF, y tengo curiosidad por saber qué hace. (El código es 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
fuente

Respuestas:

126

El ~operador NO es bit a bit , invierte los bits en un número binario:

NOT 011100
  = 100011
GWW
fuente
1
Bitwise NOT es útil para una serie de cosas, por ejemplo, máscaras de bits. No estoy seguro de lo que quiere decir con conversión de entero sin firmar a con signo.
GWW
2
Espera, ¿no se supone que debes Y la máscara de bits? así es como lo hace mi lector de bits, pero es delicado. Leí que si tiene X y NO, reste uno y obtendrá la versión sin firmar de un número firmado, ¿no es correcto?
MarcusJ
2
Utilizo NOT a nivel de bits en una máscara de bits en combinación con AND para borrar bits específicos antes de alterarlos.
GWW
2
Alguien preguntó sobre "conversión sin firmar a firmada". La operación realizada por ~también se llama "complemento a uno", que es una forma de negación binaria. Prácticamente todas las computadoras modernas usan aritmética en complemento a dos, que es la inversa bit a bit, más uno. Entonces, para una variable entera con signo x, normalmente encontrará que ~x + 1da el mismo valor que -x. Por ejemplo, printf("%hx %hx\n", -1234, ~1234 + 1)imprime fb2e fb2een mi máquina.
Steve Summit
2
@MarcusJ Sí, el complemento de uno funciona para convertir firmado a no firmado (firmado-> no firmado). (Tenga en cuenta que es más fácil simplemente asignar el valor a una variable declarada de manera diferente y dejar que el compilador se preocupe por ello). Pero no funciona al revés (sin firmar -> firmado), en parte porque los posibles valores sin firmar abarcan un rango más amplio que se puede meter en una variable con signo, y en parte porque ese problema no está bien definido sin especificar -probablemente de información externa- qué signo inventar. Sus dos comentarios obtuvieron respuestas diferentes porque especifican direcciones opuestas.
Chuck Kollars
43

~es el operador NOT bit a bit. Invierte los bits del operando.

Por ejemplo, si tiene:

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

Este es el operador NOT bit a bit. Voltea todos los bits en un número: 100110 -> 011001

inmortal
fuente
8

El carácter de tilde se utiliza como operador para invertir todos los bits de un entero (NOT bit a bit).

Por ejemplo: ~0x0044 = 0xFFBB.

Cedekasme
fuente
7

Es el operador NOT bit a bit. Invierte todos los bits en un valor entero.

Sander De Dycker
fuente
1

El operador Tilde (~) también llamado operador NOT bit a bit, realiza el complemento de cualquier número binario como argumento. Si el operando NOT es un número decimal, lo convierte en binario y realiza la operación de complemento a uno.

Para calcular el complemento a uno, simplemente invierta todos los dígitos [0 -> 1] y [1 -> 0] Ej: 0101 = 5; ~ (0101) = 1010. Uso del operador de tilde: 1. Se utiliza en la operación de enmascaramiento. Enmascarar significa establecer y restablecer los valores dentro de cualquier registro. por ejemplo:

char mask ;
mask = 1 << 5 ;

Establecerá la máscara en un valor binario de 10000 y esta máscara se puede usar para verificar el valor de bit presente dentro de otra variable.

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

Esto se llama Enmascaramiento de bits. 2. Encontrar el equivalente binario de cualquier número usando propiedades de enmascaramiento.

#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");
  }  
}

Salida: el decimal 10 es igual que 00001010

Mi observación : para el rango máximo de cualquier tipo de datos, el complemento a uno proporciona el valor negativo disminuido en 1 a cualquier valor correspondiente. ej .:
~ 1 --------> -2
~ 2 ---------> -3
y así sucesivamente ... Le mostraré esta observación usando un pequeño fragmento 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: esto es válido solo para el rango de tipo de datos. significa que para el tipo de datos int, esta regla será aplicable solo para el valor del rango [-2,147,483,648 a 2,147,483,647].
Gracias ... Que esto te ayude

Esbirro
fuente