C语言学习笔记——位运算

C语言学习笔记

位运算

进制

  • 编程通常使用的是16,10,2进制
  • 16进制通常表现为地址形式,数字有:0 1 2 3 4 5 6 7 8 9 A B C D E F,F是10进制中的15。一般有前缀标识,例如0x15A4F,字母的大小写通常不做区分。
  • 10进制是我们最熟悉的,可以进行口算,它也是最常用的进制,数字有0 1 2 3 4 5 6 7 8 9
  • 二进制是内存存储数据的形式,逢2进1,数字只有0 1
  • 它们之间的转换有两种主要算法:基数相加法和反转取余法,但是和我们的思维习惯不一致,我们在实际口算中经常使用的是两种算法的结合。

基数相加法

  • 0xAB2转换为10进制数
  • 方式:2*16^0 + B*16^1 + A*16^2
  • 0235(8)转换位10进制数
  • 方式:5*8^0 + 3*8^1 + 2*8^2
  • 0xAB2转换位8进制数
  • 方式:2*20^0 + 13*20^1 + 12*20^2也就是说要把所有的数换成八进制形式之后,再进行基数相加

反转取余法

  • 234转为8进制:连续对234除以8,取每次除得的余数,逆向打印就是结果,其他进制都用相似的方法就行。
  • 0xAB2转为8进制:最好先将AB2转为10进制,再进行计算

10、16、2进制相互转换

  • 10进制与16进制、8进制:反转取余法和基数相加法
  • 2进制与8进制、16进制:一个16进制位刚好是4个2进制位数,一个8进制位刚好是3个2进制位,因此例如对于1010 0110 1110 0001这样一个数,转化为16进制时,可以直接取每4位,来计算相对应的16进制位,结果是:A 6 E 1,也就是0xA6E1;转化为8进制时:取每3位:001 010 011 011 100 001不够的前面补0,这样算得结果是:1 2 3 3 4 1,也就是0123341

操作位的两种方式:位运算符和位字段,一个字节里面有八位,位的操作就是在这里面进行的。

按位取反运算符以及整数的存储

  • 运算符:~,其意义是得到了数据的二进制的补码,也就是说(在二进制内):~1 == 0; ~0 == 1;
  • 整个运算过程都是计算机算的,整数是按照补码的形式存储,正数的补码是本身,负数的补码是数据位按位取反再加1
  • 注意实型数据不会被支持,这是取决于其存储方式,编译器会直接报错。

按位或、按位与

  • 这两个运算符分别是:按位或|,按位与&,它们的意义是两个数进行二进制的按位比较,公式如下:

      1|1 == 1;
      1|0 == 1;
      0|0 == 0;
    
      1&1 == 1;
      1&0 == 0;
      0&0 == 0;
    
  • 这样的运算方式与逻辑运算符&&,||极为相似,理解起来比较简单。

按位异或

  • 运算符:^不同的为1,相同的为0,公式如下:

      1^1 == 0;
      0^0 == 0;
      1^0 == 1;
    
  • 浮点型怎么使用这样的运算符?浮点型不能直接使用,会直接报错,说明它没什么意义,如果非要操作,可以使用联合体:

      union
      {
      	char str[4];//或者直接定义成int型
      	float a;
      }
    
  • 初始化float,然后用str去异或,不过运行结果不太好理解。

  • 联系之前的知识:联合能做的事,强转也可以做到。*(char*)&a;这样得到数据之后再去进行操作。

移位运算符

  • 运算符有两个,位左移<<和位右移>>
  • 正数的左移、右移比较简单,就是其二进制形式的所有位向左、右移动多少位,移出去的删掉,空出来的补0,非常简单。
  • 对于负数来说,不同的系统结果可能不一样,左移没有区别,右移可能会不一样

位字段简介

  • 这个方法的移植性不太好,位运算符完全可以实现位字段的所有功能,所以说位字段以了解为主。

  • 定义:

      struct Bit
      {
      	int b8:1;
      	int b7:1;
      	int b6:1;
      	int b5:1;
      	int b4:1;
      	int b3:1;
      	int b2:1;
      	int b1:1;
      } B;
    
  • 作用是直接操作具体的某一位,给每一位起个名字。

  • 关键字也是struct

  • 注意这里涉及到了小端存储,因此第一个成员b8反而是最右侧的第一位

  • 成员类型只有三种:(位域)int;unsigned int;_Bool这三种效果一样,unsigned int用的比较多。

  • 名字:注意冒号,B这个变量有8个位(1字节)。意思是B8是一个位的名字

  • 通过这样的,控制每一个位的操作,就可以操作整个数据。
    C语言学习笔记——位运算_第1张图片

  • 上述程序的结果是41 4(图中程序的部分没有写入)4出现的原因是内存对齐。
    C语言学习笔记——位运算_第2张图片

  • 上述程序的结果是83 4,b8是两个位,能控制两个位

  • 如果改变的数据超过其最大限度,系统会警告,而且会当做能改变的最大数据处理。如上述位字段中如果B.b2 = 3;,系统会报错并当作B.b2 = 1;处理。

你可能感兴趣的:(C语言)