Chap 8:位操作
8.1 位概念
bit 比特
byte 字节 = 8 bit -> ASCII 码表的构造
记住几个常用的ASCII值: (可参考 man ascii)
0x30 -> '0'
0x41 -> 'A'
0x61 -> 'a'
8.2 位运算
四种位运算符:&或,|与,^异或, ~取反
基本技能:0x0 -> 0xF 的二进制(4-bit)表示,要求非常熟悉,正反都行
& => 得0
| => 得1
^ => 加法 (^0 则不变;^1 则反转)
~ => 得0 (构造掩码)
重要结论:
位运算不能对8bit操作,会被提升为32bit,同时会根据数据类型来扩展符号位
(无符号数扩展前面补0;有符号数扩展前面补符号位)
8.3 常见操作
1 不要把 &, | 混淆为 &&, ||
1 & 1 == 1 && 1
1 & 2 == 0 但是 1 && 2 == ture 同理类似的 5 & 10 == 0
2 取反操作用来构造数
0xFFFFFFFF == ~0x0
0xFFFFFFE0 == ~0x1F
3 运算符&,^,| 的优先级比<,>关系运算符和判等运算符== 要低
举例:
int status = 0;
if (status & 0x4000 == 0) // 条件成立,还是不成立?
重要结论:上述语句等价于 if (status & (0x4000 == 0))
8.4 移位运算
1 左移 «
左移 1位 等价于 乘2
左移时数字右边补0
2 右移 »
右移 1位 等价于 除2
右移时数字左边会补符号位 (补符号位的结果是新的负数是原来负数的一半)
8.5 范例代码
1 设置位 set bit
a |= 1<<4;
2 清除位 clear bit
a &= ~(1<<4);
3 测试位 test bit
if (a & (1<<31))
4 设置位域 set bit-field
a &= ~(0x7<<28);
a |= 0x5<<28;
5 获取位域 get bit-field
if (((a>>28) & 0x7) == 0x5)
练习题
1 计算一个任意、输入整数a中有多少个bit 1?
要求:int sum_bit_1(unsigned int a);
2 用位运算实现字符的大小写转换 (两种方法:异或,测试后修改)
要求:输入大写的字符转为小写,输入小写的字符转为大写;
3 用位运算实现对一个无符号整型的二进制打印,八进制打印,十六进制打印;
要求:
int print_bin(int a);
int print_oct(int a);
int print_hex(int a);
a = 31
二进制打印 000000000000.. 01 11 11
八进制打印 000... 0 3 7
十六进制打印 00 00 00 1F
4 用位运算实现随机生成无重复的26个字母,要求不允许使用数组
提示:随机数用 random() 函数,用一个整型数的bit0-bit25来记录已经产生的字母
用位运算实现随机生成无重复的10个数字(0-9),要求不允许使用数组
5 汉字的字符显示
请参考以下2篇技术文档, 漫谈字符集和编码 和 汉字点阵字库原理
在终端 Console 下显示 ”汉“ 字和自己的中文姓名。