Оператор тильды в C

96

Я видел оператор тильды, используемый в алгоритме хеширования ELF, и мне любопытно, что он делает. (Код взят из Eternal 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;
}
Пол Манта
источник

Ответы:

128

~Оператор побитовое НЕ , он инвертирует биты в виде двоичного числа:

NOT 011100
  = 100011
GWW
источник
1
Побитовое НЕ полезно для ряда вещей, например, для битовых масок. Я не уверен, что вы имеете в виду под беззнаковым целочисленным преобразованием со знаком.
GWW
2
Подождите, разве вы не должны И битовую маску? вот как это делает мой бит-ридер, но это обидчиво. Я читал, что если у вас есть X, а НЕ он, то вычитая один, вы получите беззнаковую версию подписанного числа, это не правильно?
MarcusJ
2
Я использую побитовое НЕ в битовой маске в сочетании с И, чтобы очистить определенные биты перед их изменением.
GWW
2
Кто-то спросил о «преобразовании без подписи в подписанное». Операция, выполняемая с помощью ~, также называется «дополнением до единицы», что является одной из форм двоичного отрицания. Практически все современные компьютеры используют арифметику с дополнением до двух, которая является побитовой инверсией плюс один. Таким образом, для целочисленной переменной со знаком xвы обычно найдете то ~x + 1же значение, что и -x. Например, printf("%hx %hx\n", -1234, ~1234 + 1)распечатывает fb2e fb2eна моей машине.
Стив Саммит,
2
@MarcusJ Да, дополнение работает для преобразования подписанного в беззнаковый (подписанный-> беззнаковый). (Обратите внимание, что проще просто присвоить значение переменной, объявленной по-другому, и позволить компилятору беспокоиться об этом.) Но это не работает наоборот (беззнаковый-> подписанный), отчасти потому, что возможные беззнаковые значения охватывают более широкий диапазон чем можно втиснуть в переменную со знаком, и отчасти потому, что эта проблема недостаточно четко определена без указания - вероятно, из внешней информации - какой знак изобретать. На ваши два комментария были даны разные ответы, потому что они указывают противоположные направления.
Чак Колларс,
43

~- побитовый оператор НЕ. Он инвертирует биты операнда.

Например, если у вас есть:

char b = 0xF0;  /* Bits are 11110000 */
char c = ~b;    /* Bits are 00001111 */
dlev
источник
12

Это побитовый оператор НЕ. Он переворачивает все биты в числе: 100110 -> 011001

бессмертный
источник
8

Символ тильды используется как оператор для инвертирования всех битов целого числа (побитовое НЕ).

Например: ~0x0044 = 0xFFBB.

Cedekasme
источник
7

Это побитовый оператор НЕ. Он инвертирует все биты в целое число.

Сандер де Дайкер
источник
1

Оператор тильды (~), также называемый побитовым оператором НЕ, выполняет дополнение любого двоичного числа в качестве аргумента. Если операнд НЕ является десятичным числом, он преобразует его в двоичное и выполняет операцию дополнения до единицы.

Чтобы вычислить дополнение, просто переверните все цифры [0 -> 1] и [1 -> 0] Пример: 0101 = 5; ~ (0101) = 1010. Использование оператора тильды: 1. Он используется в операции маскирования. Маскирование означает установку и сброс значений внутри любого регистра. например:

char mask ;
mask = 1 << 5 ;

Он установит маску на двоичное значение 10000, и эту маску можно использовать для проверки битового значения, присутствующего внутри другой переменной.

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

Это называется маскированием битов. 2. Найти двоичный эквивалент любого числа с помощью свойств маскировки.

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

Вывод: десятичное число 10 такое же, как 00001010

Мое наблюдение : для максимального диапазона любого типа данных одно дополнение обеспечивает отрицательное значение, уменьшенное на 1 до любого соответствующего значения. пример:
~ 1 --------> -2
~ 2 ---------> -3
и так далее ... Я покажу вам это наблюдение, используя небольшой фрагмент кода

#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

Примечание. Это действительно только для диапазона типов данных. означает, что для типа данных int это правило будет применяться только для значения диапазона [-2 147 483 648 до 2 147 483 647].
Спасибо ..... Может это вам поможет

Миньон
источник