Summary of operations with or or and shift of the C operator

  • 2020-05-19 05:38:27
  • OfStack

1. Analysis of xor operation (^)

The 2 yuan ^ operator is predefined for integer and bool types. For integer types, ^ will calculate the bitwise "or" of the operands. For the bool operands, ^ will calculate the logical "xor" of the operands; That is, if and only if only one operand is true, the result is true.

Numerical examples

Three features of bitwise hetero or:
(1) 0 to the 0 is 0,0 to the 1 is 1,0 or any number is any number
(2) 1 to the 0 is 1,1 to the 1 is 0,1 is either 1 or anything -- anything goes backwards
(3) 1 to the 1=0,0 to the 0=0

For example: 10100001 ^ 00010001 = 10110000

Several common USES of bitwise xor:
(1) flip certain bits
For example, if the second and third bits of logarithm 10100001 are flipped, the number can be compared with 00000110 for bitwise xor operation.
0100001 ^ 00000110 = 10100111

(2) realize the exchange of two values without using temporary variables.
For example, exchange the values of two integers a=10100001 and b=00000110, which can be achieved by the following statements:
a = a ^ b; / / a = 10100111
b = b ^ a; / / b = 10100001
a = a ^ b; / / a = 00000110

(3) in assembly language, it is often used to set variables to zero:
xor a a

(4) quickly judge whether the two values are equal
Example 1: to determine whether two integers a and b are equal, the following statements can be used:
return ((a ^ b) == 0)

Example 2: the implementation of the original ipv6_addr_equal() function in Linux is as follows:


    static inline int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2)
    {
        return (a1->s6_addr32[0] == a2->s6_addr32[0] &&
            a1->s6_addr32[1] == a2->s6_addr32[1] &&
            a1->s6_addr32[2] == a2->s6_addr32[2] &&
            a1->s6_addr32[3] == a2->s6_addr32[3]);
    }

Quick comparison can be achieved using bitwise or the latest implementation has been modified to:

    static inline int ipv6_addr_equal(const struct in6_addr *a1, const struct in6_addr *a2)
    {
    return (((a1->s6_addr32[0] ^ a2->s6_addr32[0]) |
        (a1->s6_addr32[1] ^ a2->s6_addr32[1]) |
        (a1->s6_addr32[2] ^ a2->s6_addr32[2]) |
        (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0);
    }

2 & operator (and)

1 and 0 is 0
0 and 0 are 0
1 and 1 is 1

3 | operator (or)

1 and 0 are 1
0 and 0 are 0
1 and 1 is 1

------------------

C# shift operation (left shift and right shift)

C # is used < < (left) and > > The (right shift) operator is used to perform the shift operation.

Shift to the left ( < < )

Move the first operand to the left by the number of digits specified by the second operand.
The left shift is the same thing as multiplying -- the left shift is the same thing as multiplying by 2; Moving two to the left is the same thing as multiplying by 4; So if I move 3 to the left, I multiply by 8.

x < < 1= x*2
x < < 2= x*4
x < < 3= x*8
x < < 4= x*16

Similarly, a shift to the right is the opposite:

Moves to the right ( > > )
Move the first operand to the right by the number of digits specified by the second operand.

A shift to the right is the same thing as divisible -- a shift to the right is the same thing as dividing by 2; If I move two to the right, that's the same thing as dividing by 4; So if I move 3 to the right, that's the same thing as dividing by 8.

x > > 1= x/2
x > > 2= x/4
x > > 3= x/8
x > > 4=x/16

Such as
int i = 7;
int j = 2;
Console.WriteLine(i > > j); // the output is 1

When declaring an overloaded C# shift operator, the type of the first operand must always contain the class or structure declared by the operator, and the type of the second operand must always be int, as follows:


class Program    
{        
 static void Main(string[] args)        
 {            
  ShiftClass shift1 = new ShiftClass(5, 10);            
  ShiftClass shift2 = shift1 << 2;            
  ShiftClass shift3 = shift1 >> 2;            
  Console.WriteLine("{0} << 2  As a result, :{1}", shift1.valA,  shift2.valA);            
  Console.WriteLine("{0} << 2  As a result, :{1}", shift1.valB,shift2.valB);            
  Console.WriteLine("{0} >> 2  As a result, :{1}", shift1.valA,  shift3.valA);            
  Console.WriteLine("{0} >> 2  As a result, :{1}", shift1.valB, shift3.valB);            
  Console.ReadLine();        
 }        
 public class ShiftClass        
 {           
  public int valA;           
  public int valB;            
  public ShiftClass(int valA, int valB)            
  {                
   this.valA = valA;                
   this.valB = valB;            
  }            
  public static ShiftClass operator <<(ShiftClass shift, int count)            
  {                
   int a = shift.valA << count;                
   int b = shift.valB << count;                
   return new ShiftClass(a, b);            
  }            
  public static ShiftClass operator >>(ShiftClass shift, int count)            
  {                
   int a = shift.valA >> count;                
   int b = shift.valB >> count;                
   return new ShiftClass(a, b);            
  }        
 }    
}

Because displacement is faster than multiplication and division, it requires high efficiency, and satisfies the power of 2 multiplication and division operator, so it can be carried out by displacement.


Related articles: