c及c++的位操作及其对比

  首先,我们先了解一下相关的概念,我们目前的PC机上面,普遍使用的是32位机,一个整型int为4个字节,一个char为1个字节,一个字节为8位,这里的位的概念就是今天的主角,在嵌入式领域及系统软件应用非常广泛。c/c++是很特殊的高级语言,可以直接操作位,甚至还有位域的概念,可以为一个字节中的位分别定义概念。使用位,有什么好处呢,我想应该是可以节约内存,性能较高,作为标志位时,意义非常清晰。在win32 API里面的标志位通常就是用这个来完成的,一个字节就可以用于表示32个标志了。用上|或者&操作,看起来,多么完美啊。如我们用于判断路径是否为文件夹:

WIN32_FIND_DATA fileinfo;			// File Information Structure
HANDLE		hFile;					// File Handle
hFile = FindFirstFile(sDir,&fileinfo);
// if the file exists and it is a directory
if(fileinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
	//  Directory Exists close file
	FindClose(hFile);
}else{				
	if(!CreateDirectory(sDir,NULL)){
		AfxMessageBox("本地创建目录[" + sDir + "]失败。");
		return FALSE;
	}
}

  c的位操作主要包括

操作运算符等式及结果点评
|0000 0000 | 0000 1001 = 0000 1001对每一位而言,逢1则为1
并且&0010 1111 & 1000 0000 = 0000 0000对每位计算,逢0则为0,全1才为1
取反~~1010 0111 = 01011000这个最好理解,逢1为0,逢0为1
异或^0000 1001 ^ 1010 1010 = 1010 0111两个操作位不同则为1,相同则为0
左移<<0101 1000 << 2 = 0110 0000将所有位向左边移动,并将左边的移动位抛弃,右边补0
右移>>01100000 >> 4 = 0000 0110将所有位向右边移动,右边移动位抛弃,左边补0

针对这几个运算符,我们试验一把

C的位操作#include <stdlib.h>
#include <string.h>
#include <assert.h>

void print_bit(unsigned char b)
{
	/*因无法直接访问位值,只能通过&运算来测试某位是等于或者是*/
	/*当然,现在我们这个办法是比较蠢的,因为变成你不得不得去计算这几个十六进制的值,等会再想个好点的办法*/
	printf("%c",(b & 0x80)?'1':'0');/*1000 0000*/
	printf("%c",(b & 0x40)?'1':'0');/*0100 0000*/
	printf("%c",(b & 0x20)?'1':'0');/*0010 0000*/
	printf("%c",(b & 0x10)?'1':'0');/*0001 0000*/
	printf("%c",(b & 0x08)?'1':'0');/*0000 1000*/
	printf("%c",(b & 0x04)?'1':'0');/*0000 0100*/
	printf("%c",(b & 0x02)?'1':'0');/*0000 0010*/
	printf("%c",(b & 0x01)?'1':'0');/*0000 0001*/
}

int main()
{
	/*00000000*/
	unsigned char b = 0;

	printf("初始化时:\n");
	print_bit(b);
	printf("\n----------------------------------\n\n");

	/*设置第,4位为
	00000000 | 00001001 = 00001001*/
	print_bit(b);
	b |= 0x9;
	printf(" | 00001001 = ");
	print_bit(b);
	printf("\n----------------------------------\n\n");


	/*异或
	00001001 ^ 10101010 = 10100111*/
	printf("异或^操作:");
	print_bit(b);
	printf(" ^ 10101010=");
	b ^= 0xAA;
	print_bit(b);
	printf("\n----------------------------------\n\n");

	/*取反	
	~10100111 = 01011000*/
	printf("取反~操作:~");
	print_bit(b);
	printf("=");
	b = ~b;
	print_bit(b);
	printf("\n----------------------------------\n\n");

	/*左移
	01011000 << 2 = 01100000*/
	printf("取左移<<2操作:");
	print_bit(b);
	b = b<<2;
	printf(" <<2 =");
	print_bit(b);
	printf("\n----------------------------------\n\n");

	/*右移位*/
	printf("右移>>4操作:");
	print_bit(b);
	b = b>>4;
	printf(" >>4 =");
	print_bit(b);
	printf("\n----------------------------------\n\n");

	return 0;
}

下面,我们再来看看C++的位操作是怎样的。C++的位操作,当然是STL的bitset了。

以下表摘自CPPPrimer第二版4.12

操作功能用法
test(pos)pos位是否为1?a.test(4)
any()任意位是否为1?a.any()
none()是否没有位为1?a.none()
count()值是1的位的个数a.count()
size()位元素的个数a.size()
[pos]访问pos位a[4]
flip()翻转所有的位a.flip()
set()将所有位置设为1a.set()
set(pos)将pos位置设为1a.set(4)
reset()将所有位置设为0a.reset()
reset(pos)将pos位置设为0a.reset(4)
   

 

针对上面的c程序,我们可以写出对应的c++版本,这里也不去写了,毕竟针对bitset的操作不用像C那样做麻烦的16进制的计算

总结:

bitset相对于原始C的位操作,相对直观,代码清晰,易于理解,不需要程序做机械性的2进制及16进制的换算。对于比较少接触位操作的
人们而言未尝不是一种福音,但是对于经常做位操作的嵌入式程序员来讲,估计会觉得还是直接用位操作符比较省事。也许这种差别跟Unix的
CLI(命令行模式)及WIN的GUI(窗口界面)一样,从初步来看鼠标比较易用,但对于熟练人员而言(比如程序员),往往用命令行更加的高效,且
便于批处理。扯远了。其实,从辨证的角度是不是可以两者结合使用呢?像win专注于客户端,而让unix专注于服务器呢?又一次扯远了!

 

Technorati 标签: 位操作, bitset, c, c++, 对比

 

 
 

 

 

转载于:https://www.cnblogs.com/linbc/archive/2010/02/24/1672306.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值