位操作与位操作符

//位操作与位操作符
//无论什么进制的数,其值都是每位数字与位权乘积之和
//进制对应关系:二进制转换为16进制——逢四进一,不足前面补0,八进制为逢三进一

//C\C++语言中位操作符都用于整形对象,包括char、short、int、long、long long
//  且实际因涉及到补码对有符号整数操作较少
hex     dec     bin
0       0       0000
1       1       0001
2       2       0010
3       3       0011
4       4       0100
5       5       0101
6       6       0110
7       7       0111
8       8       1000
9       9       1001
a       10      1010
b       11      1011
c       12      1100
d       13      1101
e       14      1110
f       15      1111

#include <iostream>
#include <bitset>
using namespace std;
int main() {
    //二进制字面量在C++14后引入,此前的版本用16进制代替,即0x5d
    //C++标准库中bitset类型将对象转换位指定位数的二进制字符串
    //C语言的printf()函数不支持把对象按二进制输出
    //尖括号中8为模板参数,即将c转换为8位二进制字符串

    //1.按位取反
    //对每个二进制位,1变0,0变1
    unsigned char c = 0b01011101;
    unsigned char d = ~c;
    cout << "c =  " << bitset<8>(c) << endl;
    cout << "~c = " << bitset<8>(d) << endl;

    //用途
    //(1)将每一位都取反
    //(2)使一个数最低位为0,表示为a&~1
    
    //2.按位与
    //对每个二进制位进行与运算,对应二进制位均为1时结果为1,否则为0
    unsigned int a = 0x8fff37a;
    unsigned int b = 0xfc7779f6;
    unsigned int e = a & b;
    cout << "a =     " << bitset<32>(a) << endl;	//8位16进制数即8*4=32位2进制数
    cout << "b =     " << bitset<32>(b) << endl;
    cout << "a & b = " << bitset<32>(e) << endl;
    cout << "a =              " << bitset<32>(a) << endl;
    cout << "0xfffffff7 =     " << bitset<32>(0xfffffff7) << endl;
    a &= 0xfffffff7;	//组合操作符 等价于a = a & 0xfffffff7
    cout << "a & 0xfffffff7 = " << bitset<32>(a) << endl;
    //0xfffffff7二进制下只有第3位为0,按位与操作后可使对象第3位为0
    //按位与操作可将对象特定位“置0”,同时保持其他位不变

    //用途
    //(1)清零:要将一个单元清零,即使其全部二进制位为0,只要与一个各位为0的数值相 与,结果清零
    //(2)取一个数的指定位:利用与运算将特定位之外的其他位全部“置0”

    //3.按位或
    //对每个二进制位进行或运算,对应二进制位至少有一个为1时结果为1,否则为0
    unsigned short f = 0xf37a;
    unsigned short g = 0x79f6;
    unsigned short h = f | g;
    cout << "f =     " << bitset<16>(f) << endl;	//4*4=16
    cout << "g =     " << bitset<16>(g) << endl;
    cout << "f | g = " << bitset<16>(h) << endl;
    cout << "f =          " << bitset<16>(f) << endl;
    cout << "0x0800 =     " << bitset<16>(0x0800) << endl;
    f |= 0x0800;		//组合操作符
    cout << "f | 0x0800 = " << bitset<16>(f) << endl;
    //0x0800二进制下只有第11位为0,按位或操作后可使第11位为1
    //按位或操作可将对象特定位“置1”,同时保持其他位不变 

    //用途
    //对一个数的特定位“置1”

    //4.按位异或
    //当对应二进制位不同时结果为1,否则为0
    unsigned char i = 0xb4;
    unsigned char j = 0x77;
    unsigned char k = i ^ j;
    cout << "i =     " << bitset<8>(i) << endl;
    cout << "j =     " << bitset<8>(j) << endl;
    cout << "i ^ j = " << bitset<8>(k) << endl;
    cout << "i =        " << bitset<8>(i) << endl;
    cout << "0xf0 =     " << bitset<8>(0xf0) << endl;
    i ^= 0xf0;
    cout << "i ^ 0xf0 = " << bitset<8>(i) << endl;
    //0xf0二进制下11110000,高4位将i的高4位取反,低4位同i的低4位
    //按位异或可将该数要取反的对应位设1,其余位设0

    //用途
    //使特定位取反

    //5.左移位
    //对10进制数左移2位并右方补0,相当于把该数乘上10^2
    //同理,不溢出的情况下,二进制数左移n位右方补0相当于把该数乘2^n
    unsigned short m = 5;
    cout << "m =      " << bitset<16>(m) << ",value = " << m << endl;
    m = m << 3;
    cout << "m <<= 3 =" << bitset<16>(m) << ",value = " << m << endl;

    //6.右移位
    //没有损失有效位(即右移没有1被丢弃),将无符号整数右移n位,相当于该数除2^n
    //原数为无符号整数用0填充左侧空位,有符号整数正数左补0,负数左补1
    unsigned short n = 2368;
    cout << "n =       " << bitset<16>(n) << ",value = " << n << endl;
    n = n >> 5;
    cout << "n >>= 5 = " << bitset<16>(n) << ",value = " << n << endl;

    //7.不同长度的数据进行位运算,系统会将二者按右端对齐后再进行运算 
}

//8.置位(set bit即将指定位“置1”)与复位(reset bit即将指定位“置0”)

#include <iostream>
#include <bitset>
using namespace std;
    //将v对象的第bit位置位
template <typename T>
inline void setBit(T& v, int bit) {
    v |= (0x01 << bit);
}   //0x01 << bit构造一个第bit位为1,其他全0的unsigned short
    //再把此临时对象与v做按位或运算从而将v的第bit位置位
    
    //将v对象的第bit位复位
template <typename T>
inline void resetBit(T& v, int bit) {
    v &= (~(0x01 << bit));
}   //0x01 << bit再按位取反构造一个第bit位为0,其他全为1的unsigned short
    //再把此临时对象与v做按位与运算从而将v的第bit位复位

int main() {
    unsigned short v = 0xff00;
    cout << "before v = " << bitset<16>(v) << endl;
    setBit(v, 6);
    setBit(v, 0);
    setBit(v, 11);
    resetBit(v, 15);
    resetBit(v, 10);

    cout << "after v = "<<bitset<16>(v) << endl;
    return 0;
}


//9.示例:地铁门障碍检测电路
//D1发光二极管在门左侧发出红外光;光敏三极管D2在门右侧,受光照导通,电极信号S0与地面导通为低电平
//门口有障碍物挡住D1发射红外线,D2断开,S0电阻升高为高电平
//S0信号与CPU端口管脚相连,有障碍物S0高电平,CPU认为值为1;无障碍物S0为低电平,CPU认为值为0
//地铁车厢共8节车厢16扇车门,CPU连接了S0~S15共16个传感器信号,设计程序检测哪几扇门有障碍物
#include <iostream>
#include <bitset>
using namespace std;

void testDoorSensors(unsigned short s, bool r[]) {
	for (int i = 0; i < 16; i++)
		r[i] = s & (0x01 << i);
}

int main() {
	unsigned short s = 0x4031;	//测试值
	bool blocked[16];

	cout << "s = " << bitset<16>(s) << endl;
	testDoorSensors(s, blocked);
	for (int i = 0; i < 16; i++) {
		if (blocked[i])
			cout << "Door " << i << " is blocked." << endl;
	}
	return 0;
}

//1.testDoorSensor()用于检测形参变量s的每一个二进制位,将结果存入r[]数组
//  对应二进制位为1则存入true,反之存入false
//2.0x01左移i位形成,仅第i位为1其余全0的unsigned short
//3.s与该临时对象做按位与运算,结果对象每一位都0,整个与运算结果为0,即false;
//	结果对象第i位为1,整个结果非0,即true
//4.遍历传感器变量s检测的结果数组blocked,若发现元素值为true,则报告有障碍
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值