ตัวดำเนินการทิลเดอร์ใน C


97

ฉันเคยเห็นตัวดำเนินการตัวหนอนที่ใช้ในอัลกอริทึมการแฮชของ ELF และฉันก็อยากรู้ว่ามันทำอะไร (รหัสมาจาก 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;
}

คำตอบ:


129

ตัว~ดำเนินการเป็นบิตไม่ใช่มันจะกลับบิตในเลขฐานสอง:

NOT 011100
  = 100011

1
Bitwise NOT มีประโยชน์สำหรับหลายสิ่งตัวอย่างเช่นมาสก์บิต ฉันไม่แน่ใจว่าคุณหมายถึงอะไรจากการแปลงจำนวนเต็มไม่ได้ลงชื่อ
GWW

2
เดี๋ยวก่อนคุณไม่ควรและ bitmask เหรอ? นั่นเป็นวิธีที่ผู้อ่านบิตของฉันทำ แต่มันงอน ฉันอ่านว่าถ้าคุณมี X และไม่มีมันให้ลบออกคุณจะได้หมายเลขที่ลงชื่อในเวอร์ชันที่ไม่ได้ลงชื่อนั้นไม่ถูกต้องหรือไม่?
MarcusJ

2
ฉันใช้ bitwise not บน bitmask ร่วมกับ AND เพื่อล้างบิตเฉพาะก่อนที่จะแก้ไข
GWW

2
มีคนถามเกี่ยวกับ "Conversion ที่ไม่ได้ลงชื่อเพื่อเซ็นชื่อ" การดำเนินการโดย~เรียกอีกอย่างว่า "ส่วนเติมเต็ม" ซึ่งเป็นรูปแบบหนึ่งของการปฏิเสธไบนารี คอมพิวเตอร์สมัยใหม่แทบทุกเครื่องใช้เลขคณิตเสริมสองตัวซึ่งเป็นค่าผกผันบิตบวกหนึ่ง ดังนั้นสำหรับตัวแปรจำนวนเต็มลงนามxคุณมักจะพบว่าให้ค่าเช่นเดียวกับ~x + 1 -xตัวอย่างเช่นprintf("%hx %hx\n", -1234, ~1234 + 1)พิมพ์fb2e fb2eบนเครื่องของฉัน
Steve Summit

2
@MarcusJ ใช่ส่วนเสริมของหนึ่งใช้ได้กับการแปลงเซ็นชื่อเป็นไม่ได้ลงนาม (ลงนาม -> ไม่ได้ลงนาม) (โปรดทราบว่ามันง่ายกว่าที่จะกำหนดค่าให้กับตัวแปรที่ประกาศแตกต่างกันและปล่อยให้คอมไพเลอร์กังวลกับมัน) แต่มันไม่ได้ผลในทางอื่น (ไม่ได้ลงนาม -> ลงนาม) ส่วนหนึ่งเป็นเพราะค่าที่ไม่ได้ลงชื่อที่เป็นไปได้นั้นครอบคลุมช่วงที่กว้างขึ้น กว่าจะยัดเยียดลงในตัวแปรที่ลงนามได้และส่วนหนึ่งเป็นเพราะปัญหานั้นไม่ได้ถูกกำหนดไว้อย่างชัดเจนโดยไม่ระบุ - จากข้อมูลภายนอกอาจเป็นสัญญาณที่จะคิดค้น ความคิดเห็นทั้งสองของคุณได้รับการตอบกลับที่แตกต่างกันเนื่องจากระบุทิศทางตรงกันข้าม
Chuck Kollars

43

~เป็นตัวดำเนินการไม่บิต มันจะกลับบิตของตัวถูกดำเนินการ

ตัวอย่างเช่นหากคุณมี:

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


8

อักขระทิลเดอถูกใช้เป็นตัวดำเนินการเพื่อสลับบิตทั้งหมดของจำนวนเต็ม (bitwise NOT)

ตัวอย่างเช่น: ~0x0044 = 0xFFBB.



1

ตัวดำเนินการ Tilde (~) เรียกอีกอย่างว่าตัวดำเนินการ bitwise NOT ทำหน้าที่เติมเต็มเลขฐานสองใด ๆ เป็นอาร์กิวเมนต์ หากตัวถูกดำเนินการถึงไม่เป็นเลขฐานสิบจะแปลงเป็นเลขฐานสองและดำเนินการส่วนเสริม

ในการคำนวณส่วนเติมเต็มเพียงแค่คว่ำตัวเลขทั้งหมด [0 -> 1] และ [1 -> 0] เช่น: 0101 = 5; ~ (0101) = 1010 การใช้ตัวดำเนินการทิลเดอร์: 1. ใช้ในการมาสก์การมาสก์หมายถึงการตั้งค่าและการรีเซ็ตค่าภายในรีจิสเตอร์ใด ๆ สำหรับอดีต:

char mask ;
mask = 1 << 5 ;

มันจะตั้งค่ามาสก์เป็นค่าไบนารี 10,000 และสามารถใช้มาสก์นี้เพื่อตรวจสอบค่าบิตที่มีอยู่ภายในตัวแปรอื่น

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

สิ่งนี้เรียกว่าMasking of bits 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]
ขอบคุณ ..... ขอให้สิ่งนี้ช่วยคุณได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.