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是一个位的名字
-
通过这样的,控制每一个位的操作,就可以操作整个数据。
-
上述程序的结果是
41 4
(图中程序的部分没有写入)4出现的原因是内存对齐。
-
上述程序的结果是
83 4
,b8是两个位,能控制两个位 -
如果改变的数据超过其最大限度,系统会警告,而且会当做能改变的最大数据处理。如上述位字段中如果
B.b2 = 3;
,系统会报错并当作B.b2 = 1;
处理。