Operator tyldy w C


96

Widziałem operator tyldy używany w algorytmie mieszania ELF i jestem ciekaw, co on robi. (Kod pochodzi z 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;
}

Odpowiedzi:


128

~Operator bitowe NIE , to odwraca bity w liczbie binarnej:

NOT 011100
  = 100011

1
Bitowe NIE jest przydatne do wielu rzeczy, na przykład masek bitowych. Nie jestem pewien, co masz na myśli przez konwersję bez znaku na liczby całkowite ze znakiem.
GWW

2
Czekaj, czy nie powinieneś ORAZ maski bitowej? tak właśnie robi mój czytnik bitów, ale to drażliwe. Czytałem, że jeśli masz X i NIE to, odejmij jeden, a otrzymasz niepodpisaną wersję podpisanego numeru, czy to nie jest poprawne?
MarcusJ

2
Używam bitowego NIE na masce bitowej w połączeniu z AND, aby wyczyścić określone bity przed ich zmianą.
GWW

2
Ktoś zapytał o „konwersję bez podpisu”. Operacja wykonywana przez ~jest również nazywana „dopełnieniem własnym”, co jest jedną z form binarnej negacji. Praktycznie wszystkie współczesne komputery używają arytmetyki dopełnienia do dwóch, czyli odwrotności bitowej plus jeden. Tak więc w przypadku zmiennej całkowitej ze znakiem xzwykle okaże się, że ma ~x + 1taką samą wartość jak -x. Na przykład printf("%hx %hx\n", -1234, ~1234 + 1)wydruki fb2e fb2ena moim komputerze.
Steve Summit

2
@MarcusJ Tak, uzupełnienie jednego działa w celu konwersji podpisanego na niepodpisany (podpisany-> niepodpisany). (Zauważ jednak, że łatwiej jest po prostu przypisać wartość zmiennej zadeklarowanej inaczej i pozwolić kompilatorowi się tym martwić.) Ale to nie działa w drugą stronę (bez znaku-> ze znakiem), częściowo dlatego, że możliwe wartości bez znaku obejmują szerszy zakres niż można wcisnąć w zmienną ze znakiem, a częściowo dlatego, że problem ten nie jest dobrze zdefiniowany bez określenia - prawdopodobnie z zewnętrznej informacji - jaki znak wymyślić. Twoje dwa komentarze otrzymały różne odpowiedzi, ponieważ wskazują przeciwne kierunki.
Chuck Kollars,

43

~jest operatorem bitowym NOT. Odwraca bity operandu.

Na przykład, jeśli masz:

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


8

Znak tyldy jest używany jako operator do odwracania wszystkich bitów liczby całkowitej (bitowe NIE).

Na przykład: ~0x0044 = 0xFFBB.



1

Operator tyldy (~) nazywany również operatorem bitowym NOT, jako argument wykonuje uzupełnienie dowolnej liczby binarnej. Jeśli operand NIE jest liczbą dziesiętną, to przekształca go jako binarny i wykonuje operację uzupełnienia.

Aby obliczyć dopełnienie, po prostu odwróć wszystkie cyfry [0 -> 1] i [1 -> 0] Np .: 0101 = 5; ~ (0101) = 1010. Użycie operatora tyldy: 1. Jest używany w operacji maskowania, maskowanie oznacza ustawianie i resetowanie wartości wewnątrz dowolnego rejestru. na przykład:

char mask ;
mask = 1 << 5 ;

Ustawi maskę na wartość binarną 10000, a ta maska ​​może być użyta do sprawdzenia wartości bitowej obecnej w innej zmiennej.

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

Nazywa się to maskowaniem bitów. 2. Aby znaleźć binarny odpowiednik dowolnej liczby za pomocą właściwości maskujących.

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

Dane wyjściowe: 10 dziesiętne jest takie samo jak 00001010

Moja obserwacja : dla maksymalnego zakresu dowolnego typu danych, uzupełnienie podaje wartość ujemną pomniejszoną o 1 do dowolnej odpowiadającej wartości. np.
~ 1 --------> -2
~ 2 ---------> -3
i tak dalej ... Pokażę ci tę obserwację za pomocą małego fragmentu kodu

#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

Uwaga: dotyczy to tylko zakresu typu danych. oznacza, że ​​dla typu danych int ta reguła będzie miała zastosowanie tylko do wartości zakresu [-2 147 483 648 do 2 147 483 647].
Dziękuję ..... Niech to ci pomoże

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.