#include<iostream>	//输出bitset必须用流 
#include<bitset>	//bitset所在的头文件 
#include<limits.h>  //...

using namespace std;
 
int i=-1;
unsigned int u=UINT_MAX; 

int main()
{
	
	//1.位运算运算符
//	
/*
    &  |  ^  << >>
0 0  0
0 1
1 0
1 1
*/
	cout<<"     &  |  ^  <<  >>"<<endl;
	for(int op1=0;op1<2;++op1)
		for(int op2=0;op2<2;++op2)
		{
			cout<<op1<<' '<<op2<<"  ";
			cout<<(op1&op2)<<"  "<<(op1|op2)<<"  "<<(op1^op2)<<"  "<<(op1<<op2)<<"  "<<(op1>>op2)<<endl;
		}
	cout<<endl;
	cout<<"  ~"<<endl;
	cout<<"0 "<<~0<<endl;
	cout<<"1 "<<~1<<endl<<endl;	//移位运算符用于signed时不会操作符号位,其他会
	 
	//位运算运算符的优先级甚至比iostream的优先级还要低,使用时要勤加括号!!!!!! 
	
	//bitset是一个 ♂很强大 ♂的东西
	//它可以储存一个数的二进制码流,可以用 cout 输出,也可以按位操作 
	
	//定义bitset变量格式:bitset<二进制码流位数> 变量名;
	
	//例如:
	bitset<32> bit;
	
	//可以把一个数赋值给bitset 
	//例如:
	
	bit=i;
	cout<<"(signed int)-1 = "<<bit<<endl;
	bit=u;
	cout<<"(unsigned int)2^32-1 = "<<bit<<endl<<endl;
	
	//bitset通过重载运算符的方式让它支持按位操作 
	
	bit<<=4;
	cout<<bit<<endl;
	bit>>=2;
	cout<<bit<<endl;
	bit&=1;
	cout<<bit<<endl;
	bit=1;
	cout<<bit<<endl;
	bit^=255;
	cout<<bit<<endl;
	cout<<~bit<<endl<<endl;
	
//	还可以用下标来访问bitset的位,最低位为bit[0];
	
	bit=u;
	cout<<bit<<endl;
	cout<<bit[0]<<endl;
	cout<<bit[3]<<endl<<endl;
	
//	lowbit是指一个数存在一位为 1 的最低位置
//	计算lowbit只需将这个数与这个数的补码形式按位与
//	也就是(n&-n)
	#define lowbit(n) ((n)&(-(n)))//带参数宏定义,它是简单的语句替换,要多打括号 
	bit=i;
	cout<<bit<<endl;
	cout<<lowbit(i)<<endl<<endl;
	
//	popcount统计一个数字的二进制行驶中 1 的个数
//	可以使用内建函数  __builtin_popcount()
//	long long 用 __builtin_popcountll()
//	bitset 也可以 popcount,方法是bit.count() 
//	popcount计算符号位 
	bit=-1;
	cout<<bit<<endl;
	cout<<__builtin_popcount(u)<<endl;
	cout<<bit.count()<<endl<<endl; 
//	popcount的实现方法

// 	int popcnt(int x){
//	int ret(0);
//	while(x){
//		x&=x-1;//消除最低位
//		ret++;
//	}
//	return ret;

	return 0;
}