位运算符
位运算符
所谓的位运算其实是就是针对于二进制数据的运算。在 C 语言中,常用的位运算符有以下几种:
按位与运算符:&按位或运算符:|按位异或运算符:^按位取反运算符:~左移运算符:<<右移运算符:>>
按位与
按位与运算(&)是对两个操作数的每个二进制位进行与操作,只有当对应位上的两个操作数都为1时,结果位才为1,否则为0。
关于按位与的特点可以精简为一句话:0 和任何数(0和1)都为 0。
int a = 2;
int b = 4;
int result = a & b;
- 整形数 2 对应的二进制数是
10 - 整形数 4 对应的二进制数是
100
010
& 100
------
000
通过按位与操作,我们最终得到的结果为 0。
使用按位与可以快速判断整数的奇偶性,奇数的二进制表示的最低位为1,偶数的二进制表示的最低位为0。示例:
int num = 9;
if (num & 1)
{
// num 是奇数
}
else
{
// num 是偶数
}
按位或
按位或运算(|)是对两个操作数的每个二进制位进行或操作,只要对应位上的两个操作数中至少有一个为1,结果位就为1,否则为0。
关于按位或的特点可以精简为一句话:1 和任何数(0和1)都为 1。
int a = 2;
int b = 4;
int result = a | b;
- 整形数 2 对应的二进制数是
10 - 整形数 4 对应的二进制数是
100
010
| 100
------
110
通过按位或操作,我们最终得到的二进制结果为 110,也就是十进制的 6。
按位异或
基本使用
按位异或运算(^)是对两个操作数的每个位进行异或操作,当对应位上的两个操作数不同时,结果位为1,否则为0。
关于按位异或的特点可以精简为一句话:相同为0,不同为 1。
int a = 2;
int b = 6;
int result = a ^ b;
- 整形数 2 对应的二进制数是
10 - 整形数 4 对应的二进制数是
110
010
^ 110
------
100
通过按位异或操作,最终得到的二进制结果为 100,也就是十进制的 4。
实际应用
按位异或(^)在实际应用中有以下两个常见用途(第二个个例子有循环, 可以在学完后面的知识点之后,再返回来消化吸收一下):
-
交换两个变量的值:通过按位异或可以交换两个变量的值,而不需要使用临时变量。示例:
int a = 5; int b = 7; a = a ^ b; b = a ^ b; a = a ^ b; // 现在 a = 7, b = 5 -
加密与解密:按位异或可用于简单的加密和解密算法。通过将数据与一个密钥按位异或,可以对数据进行加密。同样地,将加密后的数据再与密钥按位异或,可以解密数据。示例:
unsigned char data[] = {0x45, 0x23, 0x7F, 0x18}; unsigned char key = 0xAB; // 加密 for (int i = 0; i < sizeof(data); i++) { data[i] = data[i] ^ key; } // 解密 for (int i = 0; i < sizeof(data); i++) { data[i] = data[i] ^ key; }
这些是按位异或运算符在实际应用中的几个常见用途,但也可以根据具体需求进行其他更复杂的运算和处理。按位异或操作的特性使得它在某些场景下非常有用,可以提供高效且简单的实现方式。
按位取反
按位取反运算(~)是对操作数的每个位进行取反操作,将1变为0,将0变为1。
int a = 1;
int b = 5;
a = ~a;
b = ~b;
接下来,我们将十进制数值转换为二进制进行分析:
// 十进制的 1
~01 = 1111 1111 1111 1111 1111 1111 1111 1110
补码: 1111 1111 1111 1111 1111 1111 1111 1110
// 原码 = 补码的数据位取反 + 1 (符号位不变)
原码: 1000 0000 0000 0000 0000 0000 0000 0010
===============================================
// 十进制的 5
~101 = 1111 1111 1111 1111 1111 1111 1111 1010
补码: 1111 1111 1111 1111 1111 1111 1111 1010
// 原码 = 补码的数据位取反 + 1 (符号位不变)
原码: 1000 0000 0000 0000 0000 0000 0000 0110
根据上面的推导就可以得到如下结果:a = -2, b = -6
左移和右移
左移运算(<<)是将一个数的二进制表示向左移动指定的位数,右侧空出的位用0填充。
右移运算(>>)是将一个数的二进制表示向右移动指定的位数,左侧空出的位根据类型来填充:
- 对于有符号数,
使用算术右移,用符号位填充左侧空位 - 对于无符号数,用 0 填充左侧空位
int main()
{
int a = 6;
int b = 32;
int c = -64;
a = a << 2;
b = b >> 2;
c = c >> 3;
printf("a = %d, b = %d, c = %d\n", a, b, c);
return 0;
}
程序输出的结果为:
a = 24, b = 8, c = -8
- 对于正数,右移一位相当于除以 2,向左移一位相当于乘以 2
- 在右移操作中,负数右移一位并不严格等于除以2,而是依赖于具体的编译器实现方式,因为 C 语言中没有明确规定。一种常见的实现方式是使用算术右移,即保留符号位并用符号位填充左侧空出的位。因此,负数右移一位并不一定等于除以2。
- 对于除以2的操作,除非对被除数是无符号整数,否则建议使用除法运算符(/)来达到目的。

浙公网安备 33010602011771号