1. 首页
  2. > 代理记账 >

1010101的二进制数是多少(1010101化成十进制是多少)


在C语言中,可以单独操控变量中的位。读者可能好奇,竟然有人想这样做。有时必须单独操控位,而且非常有用。例如,通常向硬件设备发送一两个字节来控制这些设备,其中的每个位(bit)都有特定的含义。另外,与文件相关的操作信息经常被储存,通过使用特定位表明特定项。许多压缩和加密操作都是直接处理单独的位。高级语言一般不会处理这些级别的细节,C在提供高级语言使得的同时,还能在为汇编语言所保留的级别上工作,这使其成为编写设备驱动程序和嵌入式代码的首选语言。


在硬件控制中,可以用位来表示特定的信息。位运算在编程硬件设备中非常有用,因为设备的状态经常表示为一系列单独的标志(也就是字节的每个位可以表示设备各个方面的状态),在需要把一组一关标志装入单个变量中时,按位运算也非常有用。

位运算符用来操纵整型操作数中的位。unsigned类型的整数通常使用位运算符来处理。


在实际的程序设计中,有时需要存储少量的信息,这些信息并不需要占用一个完整的字节,只需占用几个或一个二进制位。例如,在存入一个标志时,只有0和1两种状态,用一个二进制即可。如果给其分配一个字节的空间,便浪费了存储空间。因此,C 引入了位域这一数据类型。


C有两种访问位的方法:按位运算符和在结构中创建位字段。


在计算机中,数据都是以二进制位(bit)表示,以字节(Byte)为最小单位进行存储。一个字节分为8位,每一位可以表示一个二进制数0或1。为了能够对一个字节中的某一位或几位进行操作,C 提供了6种位运算符。



逻辑运算符和按位运算符之间的差别在于,按位运算符返回的并非布尔值,而是对操作数对应位执行指定运算的结果。C 让您能够执行按位NOT、OR、AND和XOR运算,它们分别使用~取反、使用|对相应位执行OR运算、使用&对相应位执行AND运算、使用^对相应位执行XOR运算。其中后三个运算符对变量与选择的数字(通常是位掩码)执行相应的运算。


在整数的每位都表示特定标记的状态时,有些按位运算很有用,例如,32位的整数可用于表示32个布尔标记。


位运算的目的是用一个字节来表示更多的信息。如年份就可以使用一个字节来表示更多的信息,如用一个位来表示是31天还是30天?


位运算经常被用来创建、处理以及读取标志位序列——一种类似二进制的变量。虽然可以使用变量代替标志位序列,但是这样可以节省内存(1/32)。


信息的存取一般以字节为单位。实际上,有时存储一个信息不必用一个或多个字节,例如,“真”或“假”用0或1表示,只需1位即可。在计算机用于过程控制、参数检测或数据通信领域时,控制信息往往只占一个字节中的一个或几个二进制位,常常在一个字节中放几个信息。

1 与运算&

相同位的两个数字都为1,则为1;若有一个不为1,则为0。


与运算同与门电路相似,也类似于串联电路(1代表闭合)。


在程序中使用与运算可以进行清零操作。例如,将某个字节数据清零。可以将该字节的数据与0进行与运算,其结果将为0。因为任何数与0进行与运算,结果必然为0。此外,与运算还可以将一个字节中的某些位保留下来。例如,对于二进制数00001010,想要保留其1、3、5、7位,则可以将该二进制数与“01010101”二进制(该二进制数1、3、5、7位为1,其他位为0)进行与运算。


1.1 清零:00010010&0


1.2 保留某些位:如想保留00010010,如想保留1、3、5、7只,只需执行00010010&1010101


00010010&1的结果就是取二进制的最末位。这可以用来判断一个整数的奇偶,二进制的最末位为0表示该数为 偶数 ,最末位为1表示该数为奇数。


2 或运算 |

相同位只要一个为1即为1。


或运算通常用于二进制特定位上的无条件赋值,例如一个数 |1的结果就是把二进制最末位强行变成1。如果需要把二进制最末位变成0,对这个数 |1之后再减一就可以了,其实际意义就是把这个数强行变成最接近的偶数。


3 异或运算 ^

相同位不同则为1,相同则为0。


异或的符号是^。按位异或运算, 对等长二进制模式按位或二进制数的每一位执行逻辑按位异或操作. 操作的结果是如果某位不同则该位为1, 否则该位为0.


异或运算的逆运算是它本身,也就是说两次异或同一个数最后结果不变,即(a ^ b) ^ b = a。^运算可以用于简单的加密,比如我想对我MM说1314520,但怕别人知道,于是双方约定拿我的生日19880516作为密钥。1314520 xor 19880516 = 20665500,我就把20665500告诉MM。MM再次计算20665500 xor 19880516的值,得到1314520。


按位异或运算最经典的应用是不使用中间变量实现两个变量的互换。


int i = 5; int j = 4; i = i ^ j; j = i ^ j; i = i ^ j;

通过上述位运算后,i=4,j=5。


看运算的过程:



也可以通过替换和交换来进行理解:


首先了解一下按位异或运算的在三个性质:


I 任何数据与0进行按位异或运算,结果仍为数据本身;


II 变量与自身进行接位异或运算,结果为0;


III 按位异或运算具有交换性,即a^b^c=a^c^b=b^a^c。


i = i ^ j; ① j = i ^ j; ② i = i ^ j; ③ ②,j=i^j = ①^j= i ^ j^j=j^0=i ③,i=i^j=i^②=i^i^j=①^①^j=0^j=j

4 取反运算 ~

取反运算的定义是把内存中的0和1全部取反。使用取反运算时要格外小心,你需要注意整数类型有没有符号。如果取反的对象是无符号整数(不能表示负数),那么得到的值就是它与该类型上界的差,因为无符号类型的数是用00到$FFFF依次表示的。


5 左移运算 <<

a << b就表示把a转为二进制后左移b位(在后面添b个0)。例如100的二进制为1100100,而110010000转成十进制是400,那么100 << 2 = 400。可以看出,a << b的值实际上就是a乘以2的b次方,因为在二进制数后添一个0就相当于该数乘以2。


通常认为a << 1比a * 2更快,因为前者是更底层一些的操作。因此程序中乘以2的操作请尽量用左移一位来代替。


定义一些常量可能会用到<<运算。你可以方便地用1 << 16 - 1来表示65535。很多算法和数据结构要求数据规模必须是2的幂,此时可以用<<来定义Max_N等常量。


6 右移运算 >>

和<<相似,a >> b表示二进制右移b位(去掉末b位),相当于a除以2的b次方(取整)。我们也经常用>> 1来代替p 2,比如二分查找、堆的插入操作等等。想办法用>>代替除法运算可以使程序效率大大提高。最大公约数的二进制算法用除以2操作来代替慢得出奇的mod运算,效率可以提高60%。


实例:


#include <iostream> #include <bitset> using namespace std; void main() { unsigned int a = 21; unsigned int b = 3; cout<<(bitset<8>)21<<endl; cout<<(bitset<8>)3<<endl; cout<<(bitset<8>)(a&b)<<endl; cout<<(bitset<8>)(a|b)<<endl; cout<<(bitset<8>)(a^b)<<endl; cout<<(bitset<8>)(~a)<<endl; cout<<(bitset<8>)(a<<b)<<endl; cout<<(bitset<8>)(a>>b)<<endl; system("pause"); } /* 00010101 00000011 00000001 00010111 00010110 11101010 10101000 00000010 */

7 常用位运算实例


8 位段或位域 ( bit field)

在开发应用程序时,有时需要在一个字节中表示多项内容。例如,在描述IP协议的首部时,其首部长度占4位(bit),版本号占4位。而程序最小的空间分配单位是一个字节,即8位。在定义描述IP协议首部的结构体时,该如何实现呢? C/C 语言提供了位域,允许用户单独访问一位数据。


怎样向一个字节中的一个或几个二进制位赋值和改变它的值呢?可以用以下两种方法:


可以人为地将一个整型变量data分为几部分。


但是用这种方法给一个字节中某几位赋值太麻烦。可以位段结构体的方法。


C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或称“位域” 。利用位段能够用较少的位数存储数据。


(1)位段成员的类型必须指定为unsigned或int类型。


(2) 若某一位段要从另一个字开始存放,可用以下形式定义:


unsigned a:1; unsigned b:2;一个存储单元 unsigned:0; unsigned c:3;另一存储单元

a、b、c应连续存放在一个存储单元中,由于用了长度为0的位段,其作用是使下一个位段从下一个存储单元开始存放。因此,只将a、b存储在一个存储单元中,c另存在下一个单元(“存储单元”可能是一个字节,也可能是2个字节,视不同的编译系统而异)。


(3) 一个位段必须存储在同一存储单元中,不能跨两个单元。如果第一个单元空间不能容纳下一个位段,则该空间不用,而从下一个单元起存放该位段。


(4) 可以定义无名位段。


(5) 位段的长度不能大于存储单元的长度,也不能定义位段数组。


(6) 位段可以用整型格式符输出。


(7) 位段可以在数值表达式中引用,它会被系统自动地转换成整型数。


实例:


#include <iostream> using namespace std; typedef struct { unsigned char a:3;/*0-2位*/ unsigned char b:2;/*3-4位*/ unsigned char c:3;/*5-7位*/ }Demo; void show1010(int val){ printf("%d : ",val); for(int i=7;i>=0;i--){ //依次输出它的每一个二进制位 printf("%d",(val & 1<<i)!=0);//<<优先级高于& } printf(" "); } int main() { Demo *tt; char buf[100]; memset(buf,0,100); tt = (Demo*)&buf[0]; tt->a = 5;//101 tt->b = 2;//10 tt->c = 7;//111 //一个字节值 printf("value:%d ",buf[0]); //依次输出它的每一个二进制位 show1010(buf[0]); //当前一个字节值为: -11 //1 1 1 1 0 1 0 1 //1 1 1 1 0 1 0 1 // 7 2 5 // c b a // 要得到a值,即左边5个位与0做与运算 // 与运算 //-11 :1 1 1 1 0 1 0 1 =》 -11 //0x07 :0 0 0 0 0 1 1 1 =》 0x07 //与结果 :0 0 0 0 0 1 0 1 int a = buf[0] & 0x07; //依次输出它的每一个二进制位 show1010(a); //-11 :1 1 1 1 0 1 0 1 =》 -11 //0x07 :0 0 0 1 1 0 0 0 =》 0x18 //与结果 :0 0 0 1 0 0 0 0 // 向右边移动3位 int b = (buf[0] & 0x18) >> 3; //依次输出它的每一个二进制位 show1010(b); printf("a:%d ",a); printf("b:%d ",b); system("pause"); } /* value:-11 -11 : 11110101 5 : 00000101 2 : 00000010 a:5 b:2 */

关于位运算的一些操作,可见:


C|位运算到底能干啥?标志位的诸多应用场景


-End-


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至123456@qq.com 举报,一经查实,本站将立刻删除。

联系我们

工作日:9:30-18:30,节假日休息