L'opérateur tilde en C

95

J'ai vu l'opérateur tilde utilisé dans l'algorithme de hachage ELF, et je suis curieux de savoir ce qu'il fait. (Le code vient d'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
la source

Réponses:

126

L' ~opérateur est NON au niveau du bit , il inverse les bits en un nombre binaire:

NOT 011100
  = 100011
GWW
la source
1
Le NOT au niveau du bit est utile pour un certain nombre de choses, par exemple, les masques de bits. Je ne suis pas sûr de ce que vous entendez par conversion non signé en entier signé.
GWW
2
Attendez, n'êtes-vous pas censé ET le bitmask? c'est comme ça que mon petit lecteur le fait, mais c'est délicat. J'ai lu que si vous avez X et PAS lui, soustrayez-en un, vous obtiendrez la version non signée d'un nombre signé, n'est-ce pas correct?
MarcusJ
2
J'utilise PAS sur un bitmask en combinaison avec AND pour effacer des bits spécifiques avant de les modifier.
GWW
2
Quelqu'un a posé une question sur "conversion non signée en conversion signée". L'opération effectuée par ~est également appelée «complément à un», qui est une forme de négation binaire. Pratiquement tous les ordinateurs modernes utilisent l'arithmétique du complément à deux, qui est l'inverse au niveau du bit, plus un. Donc, pour une variable entière signée x, vous trouverez généralement que cela ~x + 1donne la même valeur que -x. Par exemple, printf("%hx %hx\n", -1234, ~1234 + 1)imprime fb2e fb2esur ma machine.
Steve Summit du
2
@MarcusJ Oui, son complément fonctionne pour la conversion signée en non signée (signé-> non signé). (Notez qu'il est plus facile d'attribuer simplement la valeur à une variable déclarée différemment et de laisser le compilateur s'en soucier.) Mais cela ne fonctionne pas dans l'autre sens (non signé -> signé), en partie parce que les valeurs non signées possibles couvrent une plage plus large qui peut être entassée dans une variable signée, et en partie parce que ce problème n'est pas bien défini sans spécifier - à partir d'informations extérieures probablement - quel signe inventer. Vos deux commentaires ont obtenu des réponses différentes car ils spécifient des directions opposées.
Chuck Kollars
43

~est l'opérateur NOT au niveau du bit. Il inverse les bits de l'opérande.

Par exemple, si vous avez:

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

Il s'agit de l'opérateur NOT au niveau du bit. Il retourne tous les bits dans un nombre: 100110 -> 011001

immortel
la source
8

Le caractère tilde est utilisé comme opérateur pour inverser tous les bits d'un entier (NON au niveau du bit).

Par exemple: ~0x0044 = 0xFFBB.

Cedekasme
la source
7

C'est l'opérateur NOT au niveau du bit. Il inverse tous les bits dans une valeur entière.

Sander De Dycker
la source
1

L'opérateur Tilde (~) également appelé opérateur NOT au niveau du bit, effectue son complément de n'importe quel nombre binaire comme argument. Si l'opérande NOT est un nombre décimal, il le convertit en binaire et effectue l'opération de complément à un.

Pour calculer son complément, il suffit d'inverser tous les chiffres [0 -> 1] et [1 -> 0] Ex: 0101 = 5; ~ (0101) = 1010. Utilisation de l'opérateur tilde: 1. Il est utilisé dans l'opération de masquage, le masquage signifie la définition et la réinitialisation des valeurs à l'intérieur de n'importe quel registre. par ex:

char mask ;
mask = 1 << 5 ;

Il définira le masque sur une valeur binaire de 10000 et ce masque peut être utilisé pour vérifier la valeur de bit présente dans une autre variable.

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

C'est ce qu'on appelle le masquage des bits. Pour trouver l'équivalent binaire de n'importe quel nombre en utilisant les propriétés de masquage.

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

Sortie: le décimal 10 est identique à 00001010

Mon observation : pour la plage maximale de tout type de données, le complément à un fournit la valeur négative diminuée de 1 à toute valeur correspondante. ex:
~ 1 --------> -2
~ 2 ---------> -3
et ainsi de suite ... Je vais vous montrer cette observation en utilisant un petit extrait de code

#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

Remarque: Ceci n'est valable que pour la plage de types de données. signifie que pour le type de données int, cette règle ne sera applicable que pour la valeur de la plage [-2 147 483 648 à 2 147 483 647].
Merci ..... Que cela vous aide

Serviteur
la source