位运算
- 定义
-
- 位运算的用途
- 位运算符
- 如何使用位运算符
-
- AND(&)运算符的用法
- OR(|)运算符的使用方法
- 如何使用XOR(^)运算符
- NOT(~)运算符的使用方法(位反转)
- 移位运算
-
- 左移(<<)运算符
- 右移(>>)运算符
- 负值的移位运算
- 结束语
定义
位运算是以二进制数的0或1表示的位为单位计算的。
在FLG的确认中经常使用,也是理解PC的结构不可缺少的项目。
在C语言中,通过使用后面说明的位运算符,可以简单地进行计算,所以要理解结构。
位运算的用途
PC以二进制数计算是一个简单的计算公式,因此处理速度往往会非常快。
在处理数百万到成千上万像素的图像时,通常会通过位运算来计算耗时的处理。
另外,由于内存使用量也有少的倾向,所以像微型计算机一样使用内存少的硬件的情况下,也经常用位运算来计算。
位运算符
位运算符是用于计算位的运算符。
就像我们在计算的时候想到的加法的“+”之类的东西。
位运算符的类型
位运算符 | 说明 |
---|---|
& | right-aligned AND。当两者都为1时,将其设置为1,否则将其设置为0的运算符 |
| | OR。只有当两者都为0时才为0。否则将其设置为1的运算符 |
^ | XOR。当两者都是不同的值时1。其他为0的运算符 |
~ | NOT。0是1,1是将其反转为0的运算符 |
>> | 通过移位运算向右偏移。它类似于十进制数所说的位移动,移动所有位的位。运算方法根据考虑或不考虑符号而不同 |
<< | 通过移位运算向左偏移 |
如何使用位运算符
在这里,因为C语言的编译器使用GCC,所以像“0b1010”一样,在数值的开头加上“0b”处理2进制数。
请注意,根据环境的不同,即使加上“0b”也不能作为二进制数来处理。
AND(&)运算符的用法
&运算符被标记为A&B,A和B都是1时为1,其他为0的运算符。
用程序看那个情况确认一下吧。
注意,我们通常使用printf函数来显示执行结果,但是printf函数不能显示二进制数。
因此,我们创建了一个二进制显示函数,并显示了计算结果。
#include <stdio.h>
// 二进制数表示的函数
void printBi(int num) {
int len = 4;
int bit[8];
int x;
for(int i = 0; i < len; i++) {
x = 1 << i;
x = num & x;
bit[len - i - 1] = x >> i;
}
printf("0b");
for(int i = 0; i < len; i++) {
printf("%d", bit[i]);
}
}
int main(void) {
int num1, num2, result;
num1 = 0b0101;
num2 = 0b0011;
result = num1 & num2;
// 用二进制数和十进制数表示运算结果
printf("二进制数:");
printBi(result);
printf("(十进制数:%d)n", result);
return 0;
}
执行结果:
上述的程序,把num1和num2 AND运算的结果变量代入result。
通过比较num1和num2的相同位数的位,您可以从程序中确认只有当两者为1时才为1。
另外,简单说明二进制数表示用的函数printBi。
我们正在使用变量x检查哪个位数的值是1。
首先,在表达式“1<<i”中,数字按顺序移位。
运算符“<<”称为左移运算符,稍后将在位移运算中详细说明。
接下来,如果要使用AND运算符“&”检查的位数为1,则返回1,否则返回0。
使用右移运算符“>>”将返回的值移位到第一位,并将结果存储在数组位元素中。
然后,由于每个数字的值被存储在数组位的每个元素中,所以它一个接一个地显示。
OR(|)运算符的使用方法
|运算符被标记为A|B,它是一个运算符,如果A和B都是0,则返回0,否则是1。用程序看那个情况确认一下吧。
#include <stdio.h>
// 二进制数表示的函数
void printBi(int num) {
int len = 4;
int bit[8];
int x;
for(int i = 0; i < len; i++) {
x = 1 << i;
x = num & x;
bit[len - i - 1] = x >> i;
}
printf("0b");
for(int i = 0; i < len; i++) {
printf("%d", bit[i]);
}
}
int main(void) {
int num1, num2, result;
num1 = 0b0101;
num2 = 0b0011;
result = num1 | num2;
// 用二进制数和十进制数表示运算结果
printf("二进制数:");
printBi(result);
printf("(十进制数:%d)n", result);
return 0;
}
执行结果:
上述的程序,num1和num2 OR运算的结果变量result代入。
通过比较num1和num2的相同位数的位,您可以从程序中确认,如果两者都为0,则为0,否则为1。
如何使用XOR(^)运算符
运算符标记为A^B,在A和B不同的情况下返回1,A和B在相同的情况下返回0。
用程序看那个情况确认一下吧。
#include <stdio.h>
// 二进制数表示的函数
void printBi(int num) {
int len = 4;
int bit[8];
int x;
for(int i = 0; i < len; i++) {
x = 1 << i;
x = num & x;
bit[len - i - 1] = x >> i;
}
printf("0b");
for(int i = 0; i < len; i++) {
printf("%d", bit[i]);
}
}
int main(void) {
int num1, num2, result;
num1 = 0b0101;
num2 = 0b0011;
result = num1 ^ num2;
// 用二进制数和十进制数表示运算结果
printf("二进制数:");
printBi(result);
printf("(十进制数:%d)n", result);
return 0;
}
执行结果:
上述的程序,num1和num2 XOR运算,其结果变量result代入。
通过比较num1和num2的相同位数的位,您可以从程序中确认只有当两者不同时才为1。
NOT(~)运算符的使用方法(位反转)
运算符是表示为~A,A为1时为0,A为0时为1的运算符。
这被称为位反转。
在位反转的情况下,也需要考虑负值,所以我们使用char类型以8位简单易懂的方式进行解释。
int类型取决于16位或32位,因为计算结果会发生变化。
让我们在实际程序中确认一下。
#include <stdio.h>
// 二进制数表示的函数
void printBi(char num) {
int len = 8;
int bit[8];
int x;
for(int i = 0; i < len; i++) {
x = 1 << i;
x = num & x;
bit[len - i - 1] = x >> i;
}
printf("0b");
for(int i = 0; i < len; i++) {
printf("%d", bit[i]);
}
}
int main(void) {
int num;
int result;
// 将0反转为1
num = 0b00000000;
result = ~num;
// 用二进制数和十进制数表示运算结果
printf("二进制数:");
printBi(result);
printf("(十进制数:%d)n", result);
// 将1反转为0
num = 0b00001111;
result = ~num;
// 用二进制数和十进制数表示运算结果
printf("二进制数:");
printBi(result);
printf("(十进制数:%d)n", result);
return 0;
}
执行结果:
二进制数:0b11111111(十进制数:-1)
二进制数:0b11110000(十进制数:-16)
上述的程序,2进制数0和2进制数1111反转表示。
可以确认,0是1,1是0,0是0。
顺便说一下,在带符号的二进制数中,最左筷子表示符号。
这叫做补数。0表示正数,1表示负数。
因此,如果在十进制数中以二进制数反转正数,则在十进制数中为负值。负值的二进制数字是通过反转所有位并添加1来创建的。
移位运算
作为应用的使用方法,解说移位运算的使用方法。
移位运算是位的位移动。
int型的话16bit还是32bit根据环境的不同而变化,所以使用char型简单易懂地用8bit进行解说。
因为以二进制数为基准来考虑,所以向左移动的话值就会翻倍,向右移动的话值就会变成1/2。
另外,需要注意的是,如果移位操作中的数字溢出,则不会成为正确的值。
左移(<<)运算符
左移运算符(<<)标记为A<<1,是将以二进制数表示的A向左移动一位数的运算符。
左移时,左侧溢出的位将被删除,右侧将添加0。
让我们在实际程序中检查左移运算。
#include <stdio.h>
// 二进制数表示的函数
void printBi(char num) {
int len = 8;
int bit[8];
int x;
for(int i = 0; i < len; i++) {
x = 1 << i;
x = num & x;
bit[len - i - 1] = x >> i;
}
printf("0b");
for(int i = 0; i < len; i++) {
printf("%d", bit[i]);
}
}
int main(void) {
char num, result;
// 十进制数的14用二进制数表示
num = 0b00001110;
printf("%dn", num);
// 将num向左移位1位
result = num << 1;
// 用二进制数和十进制数表示运算结果
printf("二进制数:");
printBi(result);
printf("(十进制数:%d)n", result);
return 0;
}
执行结果:
14
二进制数:0b00011100(十进制数:28)
上述的程序num 2进制“0000 1110”进入,num 1位左移的结果变量result代入表示。
如果将该二进制数向左移位一位数,则为“0001 1100”,因为向左偏移位数。在右端添加了0。
如果将其修改为十进制数,则是原始值“14”乘以两倍的值“28”。
右移(>>)运算符
右移运算符(>>)标记为A>>1,是将以二进制数表示的A向右移动一位数的运算符。右移时,右侧溢出的位将被删除,左侧将添加0。
让我们在实际程序中检查右移运算。
#include <stdio.h>
// 二进制数表示的函数
void printBi(char num) {
int len = 8;
int bit[8];
int x;
for(int i = 0; i < len; i++) {
x = 1 << i;
x = num & x;
bit[len - i - 1] = x >> i;
}
printf("0b");
for(int i = 0; i < len; i++) {
printf("%d", bit[i]);
}
}
int main(void) {
char num, result;
// 十进制数的14用二进制数表示
num = 0b00001110;
printf("%dn", num);
// 将num向右移位1位
result = num >> 1;
// 用二进制数和十进制数表示运算结果
printf("二进制数:");
printBi(result);
printf("(十进制数:%d)n", result);
return 0;
}
执行结果:
14
二进制数:0b00000111(十进制数:7)
上述的程序num 2进制“0000 1110”进入,num 1位右移的结果变量result代入表示。右移将数字移动到右边。
将“0000 1110”向右移位一位数,所以为“0000 0111”。
右边的数字将被删除,左边的数字将被添加到0。
如果将其修改为十进制数,则将原始值“14”设置为1/2的值的“7”。
负值的移位运算
移位运算包括逻辑移位和算术移位。
逻辑移位简单地移位所有的位。
在算术移位的情况下,移位最高有效位以外的位,以便符号不变。
请注意,在负数移位运算中,只有在右移的情况下,移位的部分左侧才会添加1。
让我们来看看实际的程序。
#include <stdio.h>
// 二进制数表示的函数
void printBi(char num) {
int len = 8;
int bit[8];
int x;
for(int i = 0; i < len; i++) {
x = 1 << i;
x = num & x;
bit[len - i - 1] = x >> i;
}
printf("0b");
for(int i = 0; i < len; i++) {
printf("%d", bit[i]);
}
}
int main(void) {
char num, result;
// 负值-14右移时
num = 0b11110010;
printf("%dn", num);
result = num >> 1;
// 用二进制数和十进制数表示运算结果
printf("二进制数:");
printBi(result);
printf("(十进制数:%d)n", result);
return 0;
}
执行结果:
-14
二进制数:0b11111001(十进制数:-7)
在上述程序中,变量num包含“1111 0010”。
在负值的情况下,左端是表示符号的位,所以即使向右移动符号也不会改变,左端进入1。因此,成为“1111 1001”。
如果将其修改为十进制数,则将原始值“-14”设置为1/2的值的“-7”。
结束语
位运算包括AND运算符、OR运算符、XOR运算符、NOT运算符、右移运算符和左移运算符。