C语言中的位运算符

你好,未来的编程巫师们!今天,我们将开始一段激动人心的旅程,深入了解C语言中的位运算符。如果你是编程新手,别担心,我会是你友好的向导,一步一步地解释一切。所以,戴上你的学习帽,让我们开始吧!

C - Bitwise Operators

位运算符是什么?

在开始之前,让我们先了解位运算符是什么。想象你有一排灯开关。位运算符就像特殊的工具,让你以有趣的方式控制这些开关——打开或关闭它们,甚至交换它们的状态。在计算机世界里,这些“开关”实际上是构成我们数据的位(0和1)。

现在,让我们逐个探索每个位运算符。

C语言中的位与运算符(&)

位与运算符就像一个挑剔的朋友,只有当两个输入都同意时才会说“是”。它比较两个数的每个位,只有当两个位都是1时才返回1,否则返回0。

来看一个例子:

#include <stdio.h>

int main() {
unsigned int a = 60;  // 60 = 0011 1100 二进制
unsigned int b = 13;  // 13 = 0000 1101 二进制

printf("a & b = %d\n", a & b);

return 0;
}

输出:

a & b = 12

这里发生了什么?让我们分解一下:

0011 1100  (60的二进制)
& 0000 1101  (13的二进制)
----------
0000 1100  (12的十进制)

看到它只保留两个数都是1的位吗?这就是位与运算符的魔力!

位或运算符(|)

位或运算符就像一个慷慨的朋友,只要任何一个输入同意就会说“是”。如果对应的位至少有一个是1,它就返回1。

这里有一个例子:

#include <stdio.h>

int main() {
unsigned int a = 60;  // 60 = 0011 1100 二进制
unsigned int b = 13;  // 13 = 0000 1101 二进制

printf("a | b = %d\n", a | b);

return 0;
}

输出:

a | b = 61

让我们分解一下:

0011 1100  (60的二进制)
| 0000 1101  (13的二进制)
----------
0011 1101  (61的十进制)

看到它保留了任何一个数是1的位吗?这就是位或运算符!

位异或运算符(^)

异或运算符就像一个古怪的朋友,喜欢事物是不同的。如果位是不同的,它返回1;如果相同,返回0。

让我们看看它是如何工作的:

#include <stdio.h>

int main() {
unsigned int a = 60;  // 60 = 0011 1100 二进制
unsigned int b = 13;  // 13 = 0000 1101 二进制

printf("a ^ b = %d\n", a ^ b);

return 0;
}

输出:

a ^ b = 49

这里发生了什么:

0011 1100  (60的二进制)
^ 0000 1101  (13的二进制)
----------
0011 0001  (49的十进制)

异或运算符经常用于加密,因为它易于反转。如果你用相同的值对一个数字进行两次异或,你会得到原始数字。很酷,对吧?

左移运算符(<<)

左移运算符就像一个向左移动位的传送带。它将每个位向左移动指定的位置数。

这里是如何工作的:

#include <stdio.h>

int main() {
unsigned int a = 60;  // 60 = 0011 1100 二进制

printf("a << 2 = %d\n", a << 2);

return 0;
}

输出:

a << 2 = 240

让我们分解一下:

0011 1100  (60的二进制)
<<2 (向左移动2位)
----------
1111 0000  (240的十进制)

注意到位是如何向左移动的,新的0从右边填充进来吗?此外,向左移动1位相当于乘以2。所以,向左移动2位就像乘以4!

右移运算符(>>)

右移运算符就像左移运算符的对立双胞胎。它将位向右移动。

让我们看一个例子:

#include <stdio.h>

int main() {
unsigned int a = 60;  // 60 = 0011 1100 二进制

printf("a >> 2 = %d\n", a >> 2);

return 0;
}

输出:

a >> 2 = 15

这里发生了什么:

0011 1100  (60的二进制)
>>2 (向右移动2位)
----------
0000 1111  (15的十进制)

位向右移动,新的0从左边填充进来。向右移动1位就像除以2(忽略余数)。

1的补码运算符(~)

1的补码运算符就像位的镜子。它将每个位从0翻转到1,反之亦然。

这里是如何工作的:

#include <stdio.h>

int main() {
unsigned int a = 60;  // 60 = 0011 1100 二进制

printf("~a = %u\n", ~a);

return 0;
}

输出:

~a = 4294967235

这里发生了什么?让我们分解一下:

0000 0000 0000 0000 0000 0000 0011 1100  (60的32位二进制)
~(1的补码)
----------------------------------------
1111 1111 1111 1111 1111 1111 1100 0011  (4294967235的十进制)

每个0变成了1,每个1变成了0。结果看起来很大,因为我们使用了一个无符号整数,它将所有这些1解释为一个正数。

结论

好了,各位!我们已经穿越了C语言中位运算符的土地。这些强大的工具可能一开始看起来有点棘手,但通过练习,你会发现它们非常有用,可以用于处理硬件、优化代码,甚至是某些很酷的派对技巧(如果你的派对涉及二进制数学的话)。

记住,掌握这些运算符的关键是练习。尝试编写自己的程序来使用这些运算符。用不同的数字进行实验,看看你得到的结果。在你意识到之前,你将能够轻松地进行位操作!

编程愉快,愿位永远眷顾你!

运算符 符号 描述
AND & 如果两个位都是1,则返回1,否则返回0
OR | 如果至少有一个位是1,则返回1,否则返回0
XOR ^ 如果位不同,则返回1;如果相同,则返回0
左移 << 将位向左移动指定的位置数
右移 >> 将位向右移动指定的位置数
1的补码 ~ 翻转所有位(0变成1,1变成0)

Credits: Image by storyset