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的位操作

下面,我们再来看看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() 将所有位置设为1 a.set()
set(pos) 将pos位置设为1 a.set(4)
reset() 将所有位置设为0 a.reset()
reset(pos) 将pos位置设为0 a.reset(4)
     

 

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

总结:

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

 

Technorati 标签: ,,,,

 


 

posted @ 2010-02-24 00:44 冷侃 阅读(...) 评论(...) 编辑 收藏