📜  C / C++中的按位运算符

📅  最后修改于: 2021-05-30 12:13:31             🧑  作者: Mango

在C中,以下6个运算符是按位运算运算符(在位级别工作)

  1. C或C++中的&(按位与)将两个数字作为操作数,并对两个数字的每一位进行“与”运算。仅当两个位均为1时,AND的结果才为1。
  2. |在C或C++中(按位或)将两个数字作为操作数,并对两个数字的每一位进行“或”运算。如果两个位中的任何一个为1,则OR的结果为1。
  3. C或C++中的^(按位XOR)将两个数字用作操作数,并对两个数字的每一位进行XOR。如果两个位不同,则XOR的结果为1。
  4. 在C或C++中, <<(左移)采用两个数字,左移第一个操作数的位,第二个操作数确定要移位的位数。
  5. C或C++中的>>(右移)采用两个数字,右移第一个操作数的位,第二个操作数确定要移位的位数。
  6. C或C++中的〜(按位NOT)取一个数字并将其所有位求反

例子:

// C Program to demonstrate use of bitwise operators
#include 
int main()
{
    // a = 5(00000101), b = 9(00001001)
    unsigned char a = 5, b = 9;
  
    // The result is 00000001
    printf("a = %d, b = %d\n", a, b);
    printf("a&b = %d\n", a & b);
  
    // The result is 00001101
    printf("a|b = %d\n", a | b);
  
    // The result is 00001100
    printf("a^b = %d\n", a ^ b);
  
    // The result is 11111010
    printf("~a = %d\n", a = ~a);
  
    // The result is 00010010
    printf("b<<1 = %d\n", b << 1);
  
    // The result is 00000100
    printf("b>>1 = %d\n", b >> 1);
  
    return 0;
}
输出:
a = 5, b = 9
a&b = 1
a|b = 13
a^b = 12
~a = 250
b<<1 = 18
b>>1 = 4

关于按位运算运算符的有趣事实

  1. 左移位运算符和右移位运算符不应用于负数。如果任何一个操作数为负数,则将导致未定义的行为。例如,-1 << 1和1 << -1的结果均未定义。另外,如果数字移位的幅度大于整数的大小,则该行为是不确定的。例如,如果使用32位存储整数,则1 << 33是未定义的。有关更多详细信息,请参见此内容。
  2. 从技术面试的角度来看,按位XOR运算符是最有用的运算符。它用于许多问题。一个简单的例子是“给出一组数字,其中所有元素除一个数字外均出现偶数次,找到奇数出现的数字”。只需对所有数字进行异或运算,就可以有效地解决此问题。
    #include 
      
    // Function to return the only odd
    // occurring element
    int findOdd(int arr[], int n)
    {
        int res = 0, i;
        for (i = 0; i < n; i++)
            res ^= arr[i];
        return res;
    }
      
    // Driver Method
    int main(void)
    {
        int arr[] = { 12, 12, 14, 90, 14, 14, 14 };
        int n = sizeof(arr) / sizeof(arr[0]);
        printf("The odd occurring element is %d ",
               findOdd(arr, n));
        return 0;
    }
    
    输出:
    The odd occurring element is 90
    

    以下是使用XOR运算符的许多其他有趣的问题。

    1. 查找丢失的号码
    2. 在不使用临时变量的情况下交换两个数字
    3. 内存有效的双链表
    4. 找到两个不重复的元素。
    5. 在未排序的数组中找到出现奇数的两个数字。
    6. 在不使用算术运算运算符的情况下将两个数字相加。
    7. 将位交换为给定的数字/。
    8. 计算要翻转以将a转换为b的位数。
    9. 找到一次出现的元素。
    10. 检测两个整数是否具有相反的符号。

  3. 不应使用按位运算运算符代替逻辑运算符。逻辑运算符(&&,||和!)的结果为0或1,但按位运算运算符返回整数值。另外,逻辑运算符会将任何非零操作数都视为1。例如,考虑以下程序,对于相同的操作数,&和&&的结果是不同的。
    #include 
      
    int main()
    {
        int x = 2, y = 5;
        (x & y) ? printf("True ") : printf("False ");
        (x && y) ? printf("True ") : printf("False ");
        return 0;
    }
    
    输出:
    False True
    
  4. 左移和右移运算符分别等效于2的乘法和除法。如第1点所述,它仅在数字为正数时起作用。
    #include 
      
    int main()
    {
        int x = 19;
        printf("x << 1 = %d\n", x << 1);
        printf("x >> 1 = %d\n", x >> 1);
        return 0;
    }
    
    输出:
    x << 1 = 38
    x >> 1 = 9
    
  5. &运算符可用于快速检查数字是否为奇数或偶数。仅当x为奇数时,表达式(x&1)的值才为非零,否则值为零。
    #include 
      
    int main()
    {
        int x = 19;
        (x & 1) ? printf("Odd") : printf("Even");
        return 0;
    }
    
    输出:
    Odd
    
  6. 〜运算符应小心使用。如果结果的〜运算符存储在一个无符号变量中,那么它的结果可能是一个很大的数字。如果结果存储在有符号变量中,则结果可能是负数(假设负数以2的补码形式存储,其中最左边的位是符号位)
    // Note that the output of the following
    // program is compiler dependent
    #include 
      
    int main()
    {
        unsigned int x = 1;
        printf("Signed Result %d \n", ~x);
        printf("Unsigned Result %ud \n", ~x);
        return 0;
    }
    
    输出:
    Signed Result -2 
    Unsigned Result 4294967294d
    

    重要链接:

    1. 位操作(重要策略)
    2. 竞争编程的按位技巧
    3. 竞争编程的位技巧
    要从最佳影片策划和实践问题去学习,检查了C++基础课程为基础,以先进的C++和C++ STL课程基础加上STL。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”