在C中,以下6个运算符是按位运算符(在位级工作)
&(按位AND)将两个数字作为操作数,并在两个数字的每个位上执行AND。仅当两个位都为1时,AND的结果才为1。
| (按位OR)将两个数字作为操作数,并在两个数字的每个位上执行OR。OR的结果是1,这两个位中的任何一个都是1。
^(按位异或)将两个数字作为操作数,并对两个数字的每个位进行异或。如果两个位不同,则XOR的结果为1。
<<(左移)取两个数字,左移第一个操作数的位,第二个操作数决定要移位的位数。
>>(右移)取两个数字,右移第一个操作数的位,第二个操作数决定要移位的位数。
〜(按位NOT)取一个数字并反转它的所有位
以下是示例C程序。
/* C Program to demonstrate use of bitwise operators */ #include<stdio.h> int main() { unsigned char a = 5, b = 9; // a = 5(00000101), b = 9(00001001) printf ( "a = %d, b = %d\n" , a, b); printf ( "a&b = %d\n" , a&b); // The result is 00000001 printf ( "a|b = %d\n" , a|b); // The result is 00001101 printf ( "a^b = %d\n" , a^b); // The result is 00001100 printf ( "~a = %d\n" , a = ~a); // The result is 11111010 printf ( "b<<1 = %d\n" , b<<1); // The result is 00010010 printf ( "b>>1 = %d\n" , b>>1); // The result is 00000100 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运算符是最有用的运算符。 它用于许多问题。一个简单的例子可能是“给定一组数字,其中除了一个数字之外所有元素都出现偶数次,找到奇数出现的数字”这个问题可以通过对所有数字进行异或来有效地解决。
// 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; } 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; } // Output: The odd occurring element is 90 |
3)不应使用按位运算符代替逻辑运算符。
逻辑运算符(&&,||和!)的结果是0或1,但按位运算符返回整数值。此外,逻辑运算符将任何非零操作数视为1.例如,考虑以下程序,&和&&的结果对于相同的操作数是不同的。
int main() { int x = 2, y = 5; (x & y)? printf ( "True " ) : printf ( "False " ); (x && y)? printf ( "True " ) : printf ( "False " ); return 0; } // Output: False True |
4)左移和右移算子分别相乘乘除和除2。
如第1点所述,只有在数字为正数时才有效。
int main() { int x = 19; printf ( "x << 1 = %d\n" , x << 1); printf ( "x >> 1 = %d\n" , x >> 1); return 0; } // Output: 38 9 |
5)&运算符可用于快速检查数字是奇数还是偶数
只有当x为奇数时,表达式(x&1)的值才为非零,否则该值为零。
int main() { int x = 19; (x & 1)? printf ( "Odd" ): printf ( "Even" ); return 0; } // Output: Odd |
6)应谨慎使用
〜运算符如果结果存储在无符号变量中,则小运算符的〜运算符的结果可以是大数。如果结果存储在有符号变量中,结果可能是负数(假设负数以2的补码形式存储,其中最左边的位是符号位)
// Note that the output of the following program is compiler dependent int main() { unsigned int x = 1; printf ( "Signed Result %d \n" , ~x); printf ( "Unsigned Result %ud \n" , ~x); return 0; } /* Output: Signed Result -2 Unsigned Result 4294967294d */ |